zario 0.2.11 → 0.3.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.
Files changed (46) hide show
  1. package/README.md +10 -1
  2. package/dist/cjs/core/CustomLogLevel.js +2 -0
  3. package/dist/cjs/core/Formatter.js +75 -0
  4. package/dist/cjs/core/LogLevel.js +2 -0
  5. package/dist/cjs/core/Logger.js +234 -0
  6. package/dist/cjs/index.js +19 -0
  7. package/dist/cjs/package.json +1 -0
  8. package/dist/cjs/transports/ConsoleTransport.js +39 -0
  9. package/dist/cjs/transports/FileTransport.js +260 -0
  10. package/dist/cjs/transports/HttpTransport.js +150 -0
  11. package/dist/cjs/transports/Transport.js +2 -0
  12. package/dist/cjs/transports/index.js +20 -0
  13. package/dist/cjs/utils/ColorUtil.js +42 -0
  14. package/dist/cjs/utils/TimeUtil.js +26 -0
  15. package/dist/cjs/utils/Timerutil.js +22 -0
  16. package/dist/{core → esm/core}/CustomLogLevel.d.ts +1 -1
  17. package/dist/esm/core/CustomLogLevel.js +1 -0
  18. package/dist/{core → esm/core}/Formatter.d.ts +1 -1
  19. package/dist/esm/core/Formatter.js +71 -0
  20. package/dist/esm/core/LogLevel.js +1 -0
  21. package/dist/{core → esm/core}/Logger.d.ts +4 -5
  22. package/dist/esm/core/Logger.js +230 -0
  23. package/dist/esm/index.d.ts +8 -0
  24. package/dist/esm/index.js +13 -0
  25. package/dist/{transports → esm/transports}/ConsoleTransport.d.ts +3 -3
  26. package/dist/esm/transports/ConsoleTransport.js +35 -0
  27. package/dist/{transports → esm/transports}/FileTransport.d.ts +7 -5
  28. package/dist/esm/transports/FileTransport.js +223 -0
  29. package/dist/{transports → esm/transports}/HttpTransport.d.ts +3 -3
  30. package/dist/esm/transports/HttpTransport.js +113 -0
  31. package/dist/{transports → esm/transports}/Transport.d.ts +2 -2
  32. package/dist/esm/transports/Transport.js +1 -0
  33. package/dist/esm/transports/index.d.ts +4 -0
  34. package/dist/esm/transports/index.js +4 -0
  35. package/dist/esm/utils/ColorUtil.js +38 -0
  36. package/dist/esm/utils/TimeUtil.js +22 -0
  37. package/dist/esm/utils/Timerutil.js +18 -0
  38. package/package.json +19 -8
  39. package/dist/index.d.ts +0 -8
  40. package/dist/index.js +0 -3
  41. package/dist/index.mjs +0 -3
  42. package/dist/transports/index.d.ts +0 -28
  43. /package/dist/{core → esm/core}/LogLevel.d.ts +0 -0
  44. /package/dist/{utils → esm/utils}/ColorUtil.d.ts +0 -0
  45. /package/dist/{utils → esm/utils}/TimeUtil.d.ts +0 -0
  46. /package/dist/{utils → esm/utils}/Timerutil.d.ts +0 -0
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FileTransport = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const zlib = __importStar(require("zlib"));
40
+ const util_1 = require("util");
41
+ const compressGzip = (0, util_1.promisify)(zlib.gzip);
42
+ const compressDeflate = (0, util_1.promisify)(zlib.deflate);
43
+ class FileTransport {
44
+ constructor(options) {
45
+ // batching funct
46
+ this.batchQueue = [];
47
+ this.batchTimer = null;
48
+ const { path: filePath, maxSize = 10 * 1024 * 1024, maxFiles = 5, compression = "none", batchInterval = 0, // no batching
49
+ compressOldFiles = true, } = options;
50
+ this.filePath = filePath;
51
+ this.maxSize = maxSize;
52
+ this.maxFiles = maxFiles;
53
+ this.compression = compression;
54
+ this.batchInterval = batchInterval;
55
+ this.compressOldFiles = compressOldFiles;
56
+ const dir = path.dirname(this.filePath);
57
+ if (!fs.existsSync(dir)) {
58
+ fs.mkdirSync(dir, { recursive: true });
59
+ }
60
+ if (!fs.existsSync(this.filePath)) {
61
+ fs.writeFileSync(this.filePath, "", "utf8");
62
+ }
63
+ // Start batching if an interval is set
64
+ if (batchInterval > 0) {
65
+ this.startBatching();
66
+ }
67
+ }
68
+ write(data, formatter) {
69
+ const output = formatter.format(data);
70
+ const formattedOutput = output + "\n";
71
+ if (this.batchInterval > 0) {
72
+ // Queue entry if batching is enabled
73
+ this.batchQueue.push({
74
+ data: formattedOutput,
75
+ timestamp: new Date(),
76
+ });
77
+ }
78
+ else {
79
+ // Write immediately when batching is disabled
80
+ fs.appendFileSync(this.filePath, formattedOutput);
81
+ if (this.shouldRotate()) {
82
+ this.rotateFiles();
83
+ }
84
+ }
85
+ }
86
+ async writeAsync(data, formatter) {
87
+ const formattedOutput = formatter.format(data) + "\n";
88
+ if (this.batchInterval > 0) {
89
+ this.batchQueue.push({
90
+ data: formattedOutput,
91
+ timestamp: new Date(),
92
+ });
93
+ }
94
+ else {
95
+ try {
96
+ await fs.promises.appendFile(this.filePath, formattedOutput);
97
+ if (this.shouldRotate()) {
98
+ await this.rotateFilesAsync();
99
+ }
100
+ }
101
+ catch (err) {
102
+ throw err;
103
+ }
104
+ }
105
+ }
106
+ shouldRotate() {
107
+ if (!fs.existsSync(this.filePath))
108
+ return false;
109
+ try {
110
+ return fs.statSync(this.filePath).size >= this.maxSize;
111
+ }
112
+ catch {
113
+ return false;
114
+ }
115
+ }
116
+ rotateFiles() {
117
+ try {
118
+ if (!fs.existsSync(this.filePath))
119
+ return;
120
+ const currentContent = fs.readFileSync(this.filePath, "utf8");
121
+ this.performRotation(currentContent, fs.writeFileSync);
122
+ this.cleanupOldFiles();
123
+ }
124
+ catch (error) {
125
+ console.error("Error during file rotation:", error);
126
+ }
127
+ }
128
+ async rotateFilesAsync() {
129
+ try {
130
+ if (!fs.existsSync(this.filePath))
131
+ return;
132
+ const currentContent = await fs.promises.readFile(this.filePath, "utf8");
133
+ await this.performRotationAsync(currentContent);
134
+ await this.cleanupOldFilesAsync();
135
+ }
136
+ catch (error) {
137
+ console.error("Error during async file rotation:", error);
138
+ }
139
+ }
140
+ performRotation(content, writeFn) {
141
+ let rotatedFilePath = this.getRotatedFilePath();
142
+ if (this.compression !== "none" && this.compressOldFiles) {
143
+ rotatedFilePath += `.${this.compression === "gzip" ? "gz" : "zz"}`;
144
+ const compressed = this.compression === "gzip" ? zlib.gzipSync(content) : zlib.deflateSync(content);
145
+ writeFn(rotatedFilePath, compressed);
146
+ }
147
+ else {
148
+ writeFn(rotatedFilePath, content, "utf8");
149
+ }
150
+ writeFn(this.filePath, "", "utf8");
151
+ }
152
+ async performRotationAsync(content) {
153
+ let rotatedFilePath = this.getRotatedFilePath();
154
+ if (this.compression !== "none" && this.compressOldFiles) {
155
+ rotatedFilePath += `.${this.compression === "gzip" ? "gz" : "zz"}`;
156
+ const compressed = this.compression === "gzip" ? await compressGzip(content) : await compressDeflate(content);
157
+ await fs.promises.writeFile(rotatedFilePath, compressed);
158
+ }
159
+ else {
160
+ await fs.promises.writeFile(rotatedFilePath, content, "utf8");
161
+ }
162
+ await fs.promises.writeFile(this.filePath, "", "utf8");
163
+ }
164
+ getRotatedFilePath() {
165
+ const dir = path.dirname(this.filePath);
166
+ return path.join(dir, `${path.basename(this.filePath)}.${Date.now()}`);
167
+ }
168
+ filterRotatedFiles(files, baseName) {
169
+ return files
170
+ .filter(f => f !== baseName && f.startsWith(baseName + "."))
171
+ .sort((a, b) => {
172
+ const getTs = (s) => parseInt(s.slice(baseName.length + 1).split(".")[0] ?? "0");
173
+ return getTs(b) - getTs(a);
174
+ });
175
+ }
176
+ cleanupOldFiles() {
177
+ const dir = path.dirname(this.filePath);
178
+ const baseName = path.basename(this.filePath);
179
+ try {
180
+ const files = fs.readdirSync(dir);
181
+ const rotated = this.filterRotatedFiles(files, baseName);
182
+ for (let i = this.maxFiles; i < rotated.length; i++) {
183
+ const file = rotated[i];
184
+ if (file) {
185
+ try {
186
+ fs.unlinkSync(path.join(dir, file));
187
+ }
188
+ catch { }
189
+ }
190
+ }
191
+ }
192
+ catch { }
193
+ }
194
+ async cleanupOldFilesAsync() {
195
+ const dir = path.dirname(this.filePath);
196
+ const baseName = path.basename(this.filePath);
197
+ try {
198
+ const files = await fs.promises.readdir(dir);
199
+ const rotated = this.filterRotatedFiles(files, baseName);
200
+ await Promise.all(rotated.slice(this.maxFiles).map(f => fs.promises.unlink(path.join(dir, f)).catch(() => { })));
201
+ }
202
+ catch { }
203
+ }
204
+ startBatching() {
205
+ if (this.batchInterval > 0) {
206
+ this.batchTimer = setInterval(() => {
207
+ this.processBatch().catch((error) => {
208
+ console.error("Error in batch processing timer:", error);
209
+ });
210
+ }, this.batchInterval);
211
+ }
212
+ }
213
+ async processBatch() {
214
+ if (this.batchQueue.length === 0) {
215
+ return;
216
+ }
217
+ // Atomically capture and clear queue
218
+ const currentBatch = this.batchQueue;
219
+ this.batchQueue = [];
220
+ // Combine queued entries into one batch
221
+ const batchContent = currentBatch.map((entry) => entry.data).join("");
222
+ try {
223
+ await new Promise((resolve, reject) => {
224
+ fs.appendFile(this.filePath, batchContent, (err) => {
225
+ if (err) {
226
+ reject(err);
227
+ return;
228
+ }
229
+ resolve();
230
+ });
231
+ });
232
+ // Rotate if needed after writing
233
+ if (this.shouldRotate()) {
234
+ await this.rotateFilesAsync();
235
+ }
236
+ }
237
+ catch (error) {
238
+ console.error("Error processing log batch:", error);
239
+ // On error, restore entries for retry (prepend to preserve order)
240
+ this.batchQueue = [...currentBatch, ...this.batchQueue];
241
+ }
242
+ }
243
+ // Clean up resources when the transport is disposed
244
+ async destroy() {
245
+ if (this.batchTimer) {
246
+ clearInterval(this.batchTimer);
247
+ this.batchTimer = null;
248
+ }
249
+ // Flush remaining queued entries
250
+ if (this.batchQueue.length > 0) {
251
+ try {
252
+ await this.processBatch();
253
+ }
254
+ catch (error) {
255
+ console.error("Error processing final batch:", error);
256
+ }
257
+ }
258
+ }
259
+ }
260
+ exports.FileTransport = FileTransport;
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.HttpTransport = void 0;
37
+ const http = __importStar(require("http"));
38
+ const https = __importStar(require("https"));
39
+ const url = __importStar(require("url"));
40
+ class HttpTransport {
41
+ constructor(options) {
42
+ const { url, method = 'POST', headers = {}, timeout = 5000, retries = 3 // defaults
43
+ } = options;
44
+ if (!url) {
45
+ throw new Error('HttpTransport requires a URL option');
46
+ }
47
+ this.url = url;
48
+ this.method = method.toUpperCase();
49
+ this.headers = { ...headers };
50
+ this.timeout = timeout;
51
+ this.retries = retries;
52
+ // Set default Content-Type if not provided
53
+ if (!this.headers['Content-Type'] && !this.headers['content-type']) {
54
+ this.headers['Content-Type'] = 'application/json';
55
+ }
56
+ }
57
+ write(data, formatter) {
58
+ // Format the data as JSON for HTTP transport
59
+ const logObject = this.parseFormattedData(data);
60
+ const body = JSON.stringify(logObject);
61
+ setImmediate(() => {
62
+ this.sendHttpRequestWithRetry(body, 0)
63
+ .catch((error) => {
64
+ console.error('HttpTransport error (sync mode):', error.message);
65
+ });
66
+ });
67
+ }
68
+ async writeAsync(data, formatter) {
69
+ // json formating for HttpTransport
70
+ const logObject = this.parseFormattedData(data);
71
+ const body = JSON.stringify(logObject);
72
+ await this.sendHttpRequestWithRetry(body, this.retries);
73
+ }
74
+ parseFormattedData(originalData) {
75
+ // structured log overide original params
76
+ return {
77
+ level: originalData.level,
78
+ message: originalData.message,
79
+ timestamp: originalData.timestamp.toISOString(),
80
+ ...(originalData.prefix && { prefix: originalData.prefix }),
81
+ ...(originalData.metadata && { metadata: originalData.metadata })
82
+ };
83
+ }
84
+ async sendHttpRequestWithRetry(body, maxRetries) {
85
+ let lastError = null;
86
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
87
+ try {
88
+ await this.sendHttpRequest(body);
89
+ return; // success then exit
90
+ }
91
+ catch (error) {
92
+ lastError = error;
93
+ // stop if last attempt
94
+ if (attempt === maxRetries) {
95
+ break;
96
+ }
97
+ // timer wait before continue
98
+ await this.delay(Math.pow(2, attempt) * 1000);
99
+ }
100
+ }
101
+ if (lastError) {
102
+ throw lastError;
103
+ }
104
+ }
105
+ sendHttpRequest(body) {
106
+ return new Promise((resolve, reject) => {
107
+ const parsedUrl = new url.URL(this.url);
108
+ const isHttps = parsedUrl.protocol === 'https:';
109
+ const client = isHttps ? https : http;
110
+ const requestOptions = {
111
+ hostname: parsedUrl.hostname,
112
+ port: parsedUrl.port,
113
+ path: parsedUrl.pathname + parsedUrl.search,
114
+ method: this.method,
115
+ headers: {
116
+ ...this.headers,
117
+ 'Content-Length': Buffer.byteLength(body, 'utf8'),
118
+ },
119
+ timeout: this.timeout,
120
+ };
121
+ const req = client.request(requestOptions, (res) => {
122
+ let responseData = '';
123
+ res.on('data', (chunk) => {
124
+ responseData += chunk;
125
+ });
126
+ res.on('end', () => {
127
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
128
+ resolve();
129
+ }
130
+ else {
131
+ reject(new Error(`HTTP request failed with status ${res.statusCode}: ${responseData}`));
132
+ }
133
+ });
134
+ });
135
+ req.on('error', (error) => {
136
+ reject(error);
137
+ });
138
+ req.on('timeout', () => {
139
+ req.destroy();
140
+ reject(new Error('Request timeout'));
141
+ });
142
+ req.write(body);
143
+ req.end();
144
+ });
145
+ }
146
+ delay(ms) {
147
+ return new Promise(resolve => setTimeout(resolve, ms));
148
+ }
149
+ }
150
+ exports.HttpTransport = HttpTransport;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Transport.js"), exports);
18
+ __exportStar(require("./ConsoleTransport.js"), exports);
19
+ __exportStar(require("./FileTransport.js"), exports);
20
+ __exportStar(require("./HttpTransport.js"), exports);
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ColorUtil = void 0;
4
+ class ColorUtil {
5
+ static colorize(text, color) {
6
+ const supportsColor = process.env.FORCE_COLOR !== "0" &&
7
+ (process.stdout.isTTY || process.env.FORCE_COLOR === "1");
8
+ if (!supportsColor) {
9
+ return text;
10
+ }
11
+ const colorCode = ColorUtil.ANSI_COLORS[color] || ColorUtil.ANSI_COLORS.reset;
12
+ return `${colorCode}${text}${ColorUtil.ANSI_COLORS.reset}`;
13
+ }
14
+ }
15
+ exports.ColorUtil = ColorUtil;
16
+ // ANSI color codes
17
+ ColorUtil.ANSI_COLORS = {
18
+ // Standard colors
19
+ black: "\x1b[30m",
20
+ red: "\x1b[31m",
21
+ green: "\x1b[32m",
22
+ yellow: "\x1b[33m",
23
+ blue: "\x1b[34m",
24
+ magenta: "\x1b[35m",
25
+ cyan: "\x1b[36m",
26
+ white: "\x1b[37m",
27
+ // Bright colors
28
+ brightRed: "\x1b[91m",
29
+ brightGreen: "\x1b[92m",
30
+ brightYellow: "\x1b[93m",
31
+ brightBlue: "\x1b[94m",
32
+ brightMagenta: "\x1b[95m",
33
+ brightCyan: "\x1b[96m",
34
+ brightWhite: "\x1b[97m",
35
+ // Default log level colors
36
+ info: "\x1b[32m",
37
+ warn: "\x1b[33m",
38
+ error: "\x1b[31m",
39
+ debug: "\x1b[36m",
40
+ boring: "\x1b[37m",
41
+ reset: "\x1b[0m",
42
+ };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimeUtil = void 0;
4
+ class TimeUtil {
5
+ // util class for date formating
6
+ static format(date, format) {
7
+ if (format === "ISO")
8
+ return date.toISOString();
9
+ if (format === "UTC")
10
+ return date.toUTCString();
11
+ if (format === "LOCAL")
12
+ return date.toLocaleString();
13
+ const pad = (n, width = 2) => n.toString().padStart(width, "0");
14
+ const tokens = {
15
+ YYYY: pad(date.getFullYear(), 4),
16
+ MM: pad(date.getMonth() + 1),
17
+ DD: pad(date.getDate()),
18
+ HH: pad(date.getHours()),
19
+ mm: pad(date.getMinutes()),
20
+ ss: pad(date.getSeconds()),
21
+ SSS: pad(date.getMilliseconds(), 3),
22
+ };
23
+ return format.replace(/YYYY|MM|DD|HH|mm|ss|SSS/g, (match) => tokens[match] || match);
24
+ }
25
+ }
26
+ exports.TimeUtil = TimeUtil;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Timer = void 0;
4
+ class Timer {
5
+ constructor(name, logFn) {
6
+ this.hasEnded = false;
7
+ this.name = name;
8
+ this.logFn = logFn;
9
+ this.startTime = Date.now();
10
+ }
11
+ end() {
12
+ // If already ended, do nothing (idempotent)
13
+ if (this.hasEnded) {
14
+ return;
15
+ }
16
+ const endTime = Date.now();
17
+ const duration = endTime - this.startTime;
18
+ this.logFn(`${this.name} took ${duration}ms`);
19
+ this.hasEnded = true;
20
+ }
21
+ }
22
+ exports.Timer = Timer;
@@ -3,4 +3,4 @@ export interface CustomLogLevelConfig {
3
3
  color: string;
4
4
  priority: number;
5
5
  }
6
- export type { LogLevel } from './LogLevel';
6
+ export type { LogLevel } from './LogLevel.js';
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { LogData } from "../types";
1
+ import { LogData } from "../types/index.js";
2
2
  export interface FormatterOptions {
3
3
  colorize?: boolean;
4
4
  json?: boolean;
@@ -0,0 +1,71 @@
1
+ import { TimeUtil } from "../utils/TimeUtil.js";
2
+ import { ColorUtil } from "../utils/ColorUtil.js";
3
+ export class Formatter {
4
+ constructor(options = {}) {
5
+ const { colorize = true, json = false, timestampFormat = "YYYY-MM-DD HH:mm:ss", timestamp = false, customColors = {}, } = options;
6
+ this.colorize = colorize;
7
+ this.json = json;
8
+ this.timestampFormat = timestampFormat;
9
+ this.timestamp = timestamp;
10
+ this.customColors = customColors;
11
+ }
12
+ format(data) {
13
+ if (this.json) {
14
+ return this.formatAsJson(data);
15
+ }
16
+ else {
17
+ return this.formatAsText(data);
18
+ }
19
+ }
20
+ formatAsJson(data) {
21
+ const formattedData = {
22
+ ...data.metadata, // Spread first so core fields can override
23
+ level: data.level,
24
+ message: data.message,
25
+ };
26
+ if (this.timestamp) {
27
+ formattedData.timestamp = data.timestamp.toISOString();
28
+ }
29
+ if (data.prefix) {
30
+ formattedData.prefix = data.prefix;
31
+ }
32
+ return JSON.stringify(formattedData);
33
+ }
34
+ formatAsText(data) {
35
+ let output = "";
36
+ if (this.timestamp) {
37
+ output += `[${TimeUtil.format(data.timestamp, this.timestampFormat)}] `;
38
+ }
39
+ if (data.prefix) {
40
+ output += `${data.prefix} `;
41
+ }
42
+ let level = data.level.toUpperCase();
43
+ if (this.colorize) {
44
+ const color = this.customColors[data.level] || data.level;
45
+ level = ColorUtil.colorize(level, color);
46
+ }
47
+ output += `[${level}] ${data.message}`;
48
+ if (data.metadata) {
49
+ output += ` ${JSON.stringify(data.metadata)}`;
50
+ }
51
+ return output;
52
+ }
53
+ setJson(json) {
54
+ this.json = json;
55
+ }
56
+ isColorized() {
57
+ return this.colorize;
58
+ }
59
+ isJson() {
60
+ return this.json;
61
+ }
62
+ getTimestampFormat() {
63
+ return this.timestampFormat;
64
+ }
65
+ hasTimestamp() {
66
+ return this.timestamp;
67
+ }
68
+ getCustomColors() {
69
+ return { ...this.customColors };
70
+ }
71
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,6 +1,6 @@
1
- import { LogLevel } from "./LogLevel";
2
- import { Transport } from "../transports";
3
- import { TransportConfig } from "../types";
1
+ import { LogLevel } from "./LogLevel.js";
2
+ import { Transport } from "../transports/Transport.js";
3
+ import { TransportConfig } from "../types/index.js";
4
4
  export interface LoggerOptions {
5
5
  level?: LogLevel;
6
6
  colorize?: boolean;
@@ -28,6 +28,7 @@ export declare class Logger {
28
28
  private asyncMode;
29
29
  private customLevels;
30
30
  private static _global;
31
+ static defaultTransportsFactory: ((isProd: boolean) => TransportConfig[]) | null;
31
32
  private static readonly LEVEL_PRIORITIES;
32
33
  prefix: string;
33
34
  timestamp: boolean;
@@ -40,12 +41,10 @@ export declare class Logger {
40
41
  private getDefaultTransports;
41
42
  private getDefaultAsyncMode;
42
43
  private initTransports;
43
- private isLegacyTransportOptions;
44
44
  private isTransport;
45
45
  private shouldLog;
46
46
  private getLevelPriority;
47
47
  private log;
48
- private logAsyncDirect;
49
48
  debug(message: string, metadata?: Record<string, any>): void;
50
49
  info(message: string, metadata?: Record<string, any>): void;
51
50
  warn(message: string, metadata?: Record<string, any>): void;