@mks2508/better-logger 0.14.0-alpha.2 → 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.
- package/dist/chunks/{Logger-Crw1woqR.js → Logger-CTAaDeZi.js} +49 -16
- package/dist/chunks/{Logger-Crw1woqR.js.map → Logger-CTAaDeZi.js.map} +1 -1
- package/dist/chunks/{Logger-D_p3xnbq.js → Logger-D8pK7XXt.js} +2 -2
- package/dist/chunks/{Logger-D_p3xnbq.js.map → Logger-D8pK7XXt.js.map} +1 -1
- package/dist/chunks/ScopedLogger-D-7q8uVP.js +2 -0
- package/dist/chunks/ScopedLogger-D-7q8uVP.js.map +1 -0
- package/dist/chunks/ScopedLogger-hS0qSkZD.js +361 -0
- package/dist/chunks/ScopedLogger-hS0qSkZD.js.map +1 -0
- package/dist/core.js +280 -307
- package/dist/exports.cjs +1 -1
- package/dist/exports.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +226 -159
- package/dist/index.js.map +1 -1
- package/dist/styling.cjs +1 -1
- package/dist/styling.js +2 -2
- package/dist/types/Logger.d.ts +11 -7
- package/dist/types/Logger.d.ts.map +1 -1
- package/dist/types/core.d.ts +122 -216
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/index.d.ts +119 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/Logger.ts +99 -58
- package/src/index.ts +32 -25
- package/dist/.tsbuildinfo +0 -1
- package/dist/Logger.d.ts +0 -708
- package/dist/Logger.d.ts.map +0 -1
- package/dist/Logger.js +0 -1124
- package/dist/ScopedLogger.d.ts +0 -318
- package/dist/ScopedLogger.d.ts.map +0 -1
- package/dist/ScopedLogger.js +0 -426
- package/dist/cli/CommandProcessor.d.ts +0 -103
- package/dist/cli/CommandProcessor.d.ts.map +0 -1
- package/dist/cli/CommandProcessor.js +0 -184
- package/dist/cli/commands/ConfigCommand.d.ts +0 -17
- package/dist/cli/commands/ConfigCommand.d.ts.map +0 -1
- package/dist/cli/commands/ConfigCommand.js +0 -88
- package/dist/cli/commands/ExportCommand.d.ts +0 -51
- package/dist/cli/commands/ExportCommand.d.ts.map +0 -1
- package/dist/cli/commands/ExportCommand.js +0 -243
- package/dist/cli/commands/HistoryCommand.d.ts +0 -50
- package/dist/cli/commands/HistoryCommand.d.ts.map +0 -1
- package/dist/cli/commands/HistoryCommand.js +0 -96
- package/dist/cli/commands/StatusCommand.d.ts +0 -33
- package/dist/cli/commands/StatusCommand.d.ts.map +0 -1
- package/dist/cli/commands/StatusCommand.js +0 -93
- package/dist/cli/commands/ThemeCommand.d.ts +0 -33
- package/dist/cli/commands/ThemeCommand.d.ts.map +0 -1
- package/dist/cli/commands/ThemeCommand.js +0 -79
- package/dist/cli/help.d.ts +0 -15
- package/dist/cli/help.d.ts.map +0 -1
- package/dist/cli/help.js +0 -118
- package/dist/cli/index.d.ts +0 -15
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -46
- package/dist/constants.d.ts +0 -122
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -159
- package/dist/core.d.ts +0 -134
- package/dist/core.d.ts.map +0 -1
- package/dist/example.d.ts +0 -18
- package/dist/example.d.ts.map +0 -1
- package/dist/example.js +0 -154
- package/dist/exports-module.d.ts +0 -203
- package/dist/exports-module.d.ts.map +0 -1
- package/dist/exports-module.js +0 -260
- package/dist/handlers/AnalyticsLogHandler.d.ts +0 -11
- package/dist/handlers/AnalyticsLogHandler.d.ts.map +0 -1
- package/dist/handlers/AnalyticsLogHandler.js +0 -19
- package/dist/handlers/ExportLogHandler.d.ts +0 -103
- package/dist/handlers/ExportLogHandler.d.ts.map +0 -1
- package/dist/handlers/ExportLogHandler.js +0 -516
- package/dist/handlers/FileLogHandler.d.ts +0 -36
- package/dist/handlers/FileLogHandler.d.ts.map +0 -1
- package/dist/handlers/FileLogHandler.js +0 -156
- package/dist/handlers/RemoteLogHandler.d.ts +0 -14
- package/dist/handlers/RemoteLogHandler.d.ts.map +0 -1
- package/dist/handlers/RemoteLogHandler.js +0 -37
- package/dist/handlers/index.d.ts +0 -8
- package/dist/handlers/index.d.ts.map +0 -1
- package/dist/handlers/index.js +0 -7
- package/dist/index.d.ts +0 -157
- package/dist/index.d.ts.map +0 -1
- package/dist/main.d.ts +0 -2
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -139
- package/dist/styling/LogStyleBuilder.d.ts +0 -149
- package/dist/styling/LogStyleBuilder.d.ts.map +0 -1
- package/dist/styling/LogStyleBuilder.js +0 -289
- package/dist/styling/SemanticStyles.d.ts +0 -181
- package/dist/styling/SemanticStyles.d.ts.map +0 -1
- package/dist/styling/SemanticStyles.js +0 -339
- package/dist/styling/SmartPresets.d.ts +0 -25
- package/dist/styling/SmartPresets.d.ts.map +0 -1
- package/dist/styling/SmartPresets.js +0 -276
- package/dist/styling/StyleBuilder.d.ts +0 -140
- package/dist/styling/StyleBuilder.d.ts.map +0 -1
- package/dist/styling/StyleBuilder.js +0 -280
- package/dist/styling/banners.d.ts +0 -45
- package/dist/styling/banners.d.ts.map +0 -1
- package/dist/styling/banners.js +0 -155
- package/dist/styling/index.d.ts +0 -10
- package/dist/styling/index.d.ts.map +0 -1
- package/dist/styling/index.js +0 -9
- package/dist/styling/themes.d.ts +0 -10
- package/dist/styling/themes.d.ts.map +0 -1
- package/dist/styling/themes.js +0 -231
- package/dist/styling-module.d.ts +0 -185
- package/dist/styling-module.d.ts.map +0 -1
- package/dist/styling-module.js +0 -199
- package/dist/types/core.js +0 -28
- package/dist/types/handlers.d.ts +0 -88
- package/dist/types/handlers.d.ts.map +0 -1
- package/dist/types/handlers.js +0 -4
- package/dist/types/index.js +0 -4
- package/dist/utils/environment.d.ts +0 -47
- package/dist/utils/environment.d.ts.map +0 -1
- package/dist/utils/environment.js +0 -85
- package/dist/utils/formatting.d.ts +0 -40
- package/dist/utils/formatting.d.ts.map +0 -1
- package/dist/utils/formatting.js +0 -117
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -6
- package/dist/utils/opentui-detection.d.ts +0 -34
- package/dist/utils/opentui-detection.d.ts.map +0 -1
- package/dist/utils/opentui-detection.js +0 -116
- package/dist/utils/output.d.ts +0 -44
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/output.js +0 -150
- package/dist/utils/stackTrace.d.ts +0 -9
- package/dist/utils/stackTrace.d.ts.map +0 -1
- package/dist/utils/stackTrace.js +0 -81
- package/dist/utils/timestamps.d.ts +0 -20
- package/dist/utils/timestamps.d.ts.map +0 -1
- package/dist/utils/timestamps.js +0 -71
|
@@ -1,516 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Export and clipboard log handler for Advanced Logger
|
|
3
|
-
*/
|
|
4
|
-
import { parseTimeInput, formatDisplayTime, safeStringify, escapeHtml, generateLogId } from '../utils/index.js';
|
|
5
|
-
import { BUFFER_LIMITS } from '../constants.js';
|
|
6
|
-
/**
|
|
7
|
-
* Export log handler with circular buffer and multiple export formats
|
|
8
|
-
*/
|
|
9
|
-
export class ExportLogHandler {
|
|
10
|
-
buffer = [];
|
|
11
|
-
maxSize;
|
|
12
|
-
groupDepth = 0;
|
|
13
|
-
currentGroup;
|
|
14
|
-
constructor(maxSize = BUFFER_LIMITS.DEFAULT_SIZE) {
|
|
15
|
-
this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Handle incoming log and store in buffer
|
|
19
|
-
*/
|
|
20
|
-
handle(level, message, args, metadata) {
|
|
21
|
-
const entry = {
|
|
22
|
-
id: generateLogId(),
|
|
23
|
-
timestamp: metadata.timestamp,
|
|
24
|
-
level,
|
|
25
|
-
prefix: metadata.prefix,
|
|
26
|
-
message,
|
|
27
|
-
args,
|
|
28
|
-
location: metadata.stackInfo,
|
|
29
|
-
groupInfo: this.groupDepth > 0 ? {
|
|
30
|
-
depth: this.groupDepth,
|
|
31
|
-
groupName: this.currentGroup
|
|
32
|
-
} : undefined
|
|
33
|
-
};
|
|
34
|
-
// Add to circular buffer
|
|
35
|
-
this.buffer.push(entry);
|
|
36
|
-
if (this.buffer.length > this.maxSize) {
|
|
37
|
-
this.buffer.shift(); // Remove oldest entry
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Set group tracking for nested logs
|
|
42
|
-
*/
|
|
43
|
-
setGroupInfo(depth, groupName) {
|
|
44
|
-
this.groupDepth = depth;
|
|
45
|
-
this.currentGroup = groupName;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Get buffer statistics
|
|
49
|
-
*/
|
|
50
|
-
getBufferStats() {
|
|
51
|
-
const levelCounts = this.buffer.reduce((acc, entry) => {
|
|
52
|
-
const currentCount = acc[entry.level] ? acc[entry.level] : 0;
|
|
53
|
-
acc[entry.level] = currentCount + 1;
|
|
54
|
-
return acc;
|
|
55
|
-
}, {});
|
|
56
|
-
let oldestLog;
|
|
57
|
-
let newestLog;
|
|
58
|
-
if (this.buffer.length > 0) {
|
|
59
|
-
const firstEntry = this.buffer[0];
|
|
60
|
-
const lastEntry = this.buffer[this.buffer.length - 1];
|
|
61
|
-
if (firstEntry && firstEntry.timestamp) {
|
|
62
|
-
oldestLog = new Date(firstEntry.timestamp);
|
|
63
|
-
}
|
|
64
|
-
if (lastEntry && lastEntry.timestamp) {
|
|
65
|
-
newestLog = new Date(lastEntry.timestamp);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
size: this.buffer.length,
|
|
70
|
-
maxSize: this.maxSize,
|
|
71
|
-
usage: (this.buffer.length / this.maxSize) * 100,
|
|
72
|
-
oldestLog,
|
|
73
|
-
newestLog,
|
|
74
|
-
levelCounts: {
|
|
75
|
-
debug: levelCounts.debug ? levelCounts.debug : 0,
|
|
76
|
-
info: levelCounts.info ? levelCounts.info : 0,
|
|
77
|
-
warn: levelCounts.warn ? levelCounts.warn : 0,
|
|
78
|
-
error: levelCounts.error ? levelCounts.error : 0,
|
|
79
|
-
critical: levelCounts.critical ? levelCounts.critical : 0
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Clear the buffer
|
|
85
|
-
*/
|
|
86
|
-
clearBuffer() {
|
|
87
|
-
this.buffer = [];
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Set buffer size (with limits)
|
|
91
|
-
*/
|
|
92
|
-
setBufferSize(size) {
|
|
93
|
-
this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
|
|
94
|
-
// Trim buffer if new size is smaller
|
|
95
|
-
if (this.buffer.length > this.maxSize) {
|
|
96
|
-
this.buffer = this.buffer.slice(-this.maxSize);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Filter logs based on criteria
|
|
101
|
-
*/
|
|
102
|
-
filterLogs(filters = {}) {
|
|
103
|
-
let filtered = [...this.buffer];
|
|
104
|
-
// Filter by levels
|
|
105
|
-
if (filters.levels?.length) {
|
|
106
|
-
filtered = filtered.filter(entry => filters.levels.includes(entry.level));
|
|
107
|
-
}
|
|
108
|
-
// Filter by prefixes
|
|
109
|
-
if (filters.prefixes?.length) {
|
|
110
|
-
filtered = filtered.filter(entry => entry.prefix && filters.prefixes.includes(entry.prefix));
|
|
111
|
-
}
|
|
112
|
-
// Exclude prefixes
|
|
113
|
-
if (filters.excludePrefixes?.length) {
|
|
114
|
-
filtered = filtered.filter(entry => !entry.prefix || !filters.excludePrefixes.includes(entry.prefix));
|
|
115
|
-
}
|
|
116
|
-
// Filter by time range
|
|
117
|
-
if (filters.since) {
|
|
118
|
-
const sinceDate = parseTimeInput(filters.since);
|
|
119
|
-
filtered = filtered.filter(entry => new Date(entry.timestamp) >= sinceDate);
|
|
120
|
-
}
|
|
121
|
-
if (filters.until) {
|
|
122
|
-
const untilDate = parseTimeInput(filters.until);
|
|
123
|
-
filtered = filtered.filter(entry => new Date(entry.timestamp) <= untilDate);
|
|
124
|
-
}
|
|
125
|
-
// Filter by stack trace presence
|
|
126
|
-
if (filters.withStackTrace) {
|
|
127
|
-
filtered = filtered.filter(entry => entry.location);
|
|
128
|
-
}
|
|
129
|
-
// Filter errors only
|
|
130
|
-
if (filters.errorsOnly) {
|
|
131
|
-
filtered = filtered.filter(entry => entry.level === 'error' || entry.level === 'critical');
|
|
132
|
-
}
|
|
133
|
-
// Search in messages
|
|
134
|
-
if (filters.search) {
|
|
135
|
-
const searchTerm = filters.search.toLowerCase();
|
|
136
|
-
filtered = filtered.filter(entry => entry.message.toLowerCase().includes(searchTerm) ||
|
|
137
|
-
entry.args.some(arg => String(arg).toLowerCase().includes(searchTerm)));
|
|
138
|
-
}
|
|
139
|
-
// Limit results
|
|
140
|
-
if (filters.last) {
|
|
141
|
-
filtered = filtered.slice(-filters.last);
|
|
142
|
-
}
|
|
143
|
-
if (filters.first) {
|
|
144
|
-
filtered = filtered.slice(0, filters.first);
|
|
145
|
-
}
|
|
146
|
-
return filtered;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Export logs in JSON format
|
|
150
|
-
*/
|
|
151
|
-
exportJSON(logs, options) {
|
|
152
|
-
const data = logs.map(entry => ({
|
|
153
|
-
timestamp: entry.timestamp,
|
|
154
|
-
level: entry.level,
|
|
155
|
-
prefix: entry.prefix,
|
|
156
|
-
message: entry.message,
|
|
157
|
-
...(options.minimal ? {} : {
|
|
158
|
-
args: entry.args.slice(1),
|
|
159
|
-
location: entry.location,
|
|
160
|
-
groupInfo: entry.groupInfo
|
|
161
|
-
})
|
|
162
|
-
}));
|
|
163
|
-
return options.compact
|
|
164
|
-
? JSON.stringify(data)
|
|
165
|
-
: JSON.stringify(data, null, 2);
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Export logs in CSV format
|
|
169
|
-
*/
|
|
170
|
-
exportCSV(logs, options) {
|
|
171
|
-
const headers = options.minimal
|
|
172
|
-
? ['Timestamp', 'Level', 'Prefix', 'Message']
|
|
173
|
-
: ['Timestamp', 'Level', 'Prefix', 'Message', 'File', 'Line', 'Args'];
|
|
174
|
-
const rows = logs.map(entry => {
|
|
175
|
-
const baseRow = [
|
|
176
|
-
formatDisplayTime(new Date(entry.timestamp), 'full'),
|
|
177
|
-
entry.level.toUpperCase(),
|
|
178
|
-
entry.prefix || '',
|
|
179
|
-
`"${entry.message.replace(/"/g, '""')}"`
|
|
180
|
-
];
|
|
181
|
-
if (!options.minimal) {
|
|
182
|
-
baseRow.push(entry.location?.file || '', entry.location?.line?.toString() || '', `"${safeStringify(entry.args.slice(1)).replace(/"/g, '""')}"`);
|
|
183
|
-
}
|
|
184
|
-
return baseRow;
|
|
185
|
-
});
|
|
186
|
-
return [headers.join(','), ...rows.map(row => row.join(','))].join('\n');
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Export logs in Markdown format
|
|
190
|
-
*/
|
|
191
|
-
exportMarkdown(logs, options) {
|
|
192
|
-
const now = new Date();
|
|
193
|
-
let content = `# Log Export - ${formatDisplayTime(now, 'full')}\n\n`;
|
|
194
|
-
// Add summary if not minimal
|
|
195
|
-
if (!options.minimal) {
|
|
196
|
-
const summary = this.getBufferStats();
|
|
197
|
-
content += `## Summary\n`;
|
|
198
|
-
content += `- **Total logs**: ${logs.length}\n`;
|
|
199
|
-
content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}\n`;
|
|
200
|
-
content += `- **Warnings**: ${summary.levelCounts.warn}\n\n`;
|
|
201
|
-
}
|
|
202
|
-
// Group by level if specified
|
|
203
|
-
if (options.groupBy === 'level') {
|
|
204
|
-
const grouped = logs.reduce((acc, entry) => {
|
|
205
|
-
const level = entry.level;
|
|
206
|
-
if (!acc[level]) {
|
|
207
|
-
acc[level] = [];
|
|
208
|
-
}
|
|
209
|
-
// We just ensured the array exists above
|
|
210
|
-
const levelArray = acc[level];
|
|
211
|
-
if (levelArray) {
|
|
212
|
-
levelArray.push(entry);
|
|
213
|
-
}
|
|
214
|
-
return acc;
|
|
215
|
-
}, {});
|
|
216
|
-
Object.entries(grouped).forEach(([level, entries]) => {
|
|
217
|
-
const emoji = this.getLevelEmoji(level);
|
|
218
|
-
content += `## ${emoji} ${level.toUpperCase()} (${entries.length})\n\n`;
|
|
219
|
-
entries.forEach(entry => {
|
|
220
|
-
const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');
|
|
221
|
-
const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';
|
|
222
|
-
const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';
|
|
223
|
-
content += `- \`${time}\`${prefix} ${entry.message}${location}\n`;
|
|
224
|
-
});
|
|
225
|
-
content += '\n';
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
content += '## Logs\n\n';
|
|
230
|
-
logs.forEach(entry => {
|
|
231
|
-
const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');
|
|
232
|
-
const emoji = this.getLevelEmoji(entry.level);
|
|
233
|
-
const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';
|
|
234
|
-
const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';
|
|
235
|
-
content += `- \`${time}\` ${emoji}${prefix} ${entry.message}${location}\n`;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
return content;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Export logs in plain text format
|
|
242
|
-
*/
|
|
243
|
-
exportPlain(logs, options) {
|
|
244
|
-
return logs.map(entry => {
|
|
245
|
-
const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? 'time-only' : 'short');
|
|
246
|
-
const level = entry.level.toUpperCase().padEnd(8);
|
|
247
|
-
const prefix = entry.prefix ? `[${entry.prefix}] ` : '';
|
|
248
|
-
const location = (!options.minimal && entry.location) ? ` (${entry.location.file}:${entry.location.line})` : '';
|
|
249
|
-
return `${time} ${level} ${prefix}${entry.message}${location}`;
|
|
250
|
-
}).join('\n');
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Export logs in HTML format
|
|
254
|
-
*/
|
|
255
|
-
exportHTML(logs, _options) {
|
|
256
|
-
const title = `Log Export - ${formatDisplayTime(new Date(), 'full')}`;
|
|
257
|
-
let html = `<!DOCTYPE html>
|
|
258
|
-
<html lang="en">
|
|
259
|
-
<head>
|
|
260
|
-
<meta charset="UTF-8">
|
|
261
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
262
|
-
<title>${title}</title>
|
|
263
|
-
<style>
|
|
264
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }
|
|
265
|
-
.header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }
|
|
266
|
-
.log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }
|
|
267
|
-
.timestamp { color: #666; font-size: 0.9em; }
|
|
268
|
-
.level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
|
|
269
|
-
.prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
|
|
270
|
-
.location { color: #718096; font-size: 0.9em; }
|
|
271
|
-
.debug { background: #f0f4ff; }
|
|
272
|
-
.info { background: #f0f9ff; }
|
|
273
|
-
.warn { background: #fffbeb; }
|
|
274
|
-
.error { background: #fef2f2; }
|
|
275
|
-
.critical { background: #fef2f2; border-left: 4px solid #dc2626; }
|
|
276
|
-
.level.debug { background: #667eea; color: white; }
|
|
277
|
-
.level.info { background: #74b9ff; color: white; }
|
|
278
|
-
.level.warn { background: #fdcb6e; color: #2d3436; }
|
|
279
|
-
.level.error { background: #e84393; color: white; }
|
|
280
|
-
.level.critical { background: #ff3838; color: white; }
|
|
281
|
-
</style>
|
|
282
|
-
</head>
|
|
283
|
-
<body>
|
|
284
|
-
<div class="header">
|
|
285
|
-
<h1>${title}</h1>
|
|
286
|
-
<p>Generated by Advanced Logger v2.0.0</p>
|
|
287
|
-
</div>
|
|
288
|
-
<div class="logs">`;
|
|
289
|
-
logs.forEach(entry => {
|
|
290
|
-
const time = formatDisplayTime(new Date(entry.timestamp), 'full');
|
|
291
|
-
const location = entry.location ? ` <span class="location">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : '';
|
|
292
|
-
const prefix = entry.prefix ? ` <span class="prefix">${escapeHtml(entry.prefix)}</span>` : '';
|
|
293
|
-
html += `
|
|
294
|
-
<div class="log-entry ${entry.level}">
|
|
295
|
-
<span class="timestamp">${time}</span>
|
|
296
|
-
<span class="level ${entry.level}">${entry.level.toUpperCase()}</span>
|
|
297
|
-
${prefix}
|
|
298
|
-
<span class="message">${escapeHtml(entry.message)}</span>
|
|
299
|
-
${location}
|
|
300
|
-
</div>`;
|
|
301
|
-
});
|
|
302
|
-
html += `
|
|
303
|
-
</div>
|
|
304
|
-
</body>
|
|
305
|
-
</html>`;
|
|
306
|
-
return html;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Get emoji for log level
|
|
310
|
-
*/
|
|
311
|
-
getLevelEmoji(level) {
|
|
312
|
-
const emojis = {
|
|
313
|
-
debug: '🐞',
|
|
314
|
-
info: 'ℹ️',
|
|
315
|
-
warn: '⚠️',
|
|
316
|
-
error: '❌',
|
|
317
|
-
critical: '🔥'
|
|
318
|
-
};
|
|
319
|
-
return emojis[level] || '';
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Main export function
|
|
323
|
-
*/
|
|
324
|
-
export(format, filters = {}, options = {}) {
|
|
325
|
-
const filteredLogs = this.filterLogs(filters);
|
|
326
|
-
let data;
|
|
327
|
-
switch (format) {
|
|
328
|
-
case 'json':
|
|
329
|
-
data = this.exportJSON(filteredLogs, options);
|
|
330
|
-
break;
|
|
331
|
-
case 'csv':
|
|
332
|
-
data = this.exportCSV(filteredLogs, options);
|
|
333
|
-
break;
|
|
334
|
-
case 'markdown':
|
|
335
|
-
data = this.exportMarkdown(filteredLogs, options);
|
|
336
|
-
break;
|
|
337
|
-
case 'plain':
|
|
338
|
-
data = this.exportPlain(filteredLogs, options);
|
|
339
|
-
break;
|
|
340
|
-
case 'html':
|
|
341
|
-
data = this.exportHTML(filteredLogs, options);
|
|
342
|
-
break;
|
|
343
|
-
default:
|
|
344
|
-
throw new Error(`Unsupported export format: ${format}`);
|
|
345
|
-
}
|
|
346
|
-
return {
|
|
347
|
-
format,
|
|
348
|
-
data,
|
|
349
|
-
metadata: {
|
|
350
|
-
totalLogs: this.buffer.length,
|
|
351
|
-
filteredLogs: filteredLogs.length,
|
|
352
|
-
exportedAt: new Date().toISOString(),
|
|
353
|
-
filters,
|
|
354
|
-
options
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Copy to clipboard with fallback
|
|
360
|
-
*/
|
|
361
|
-
async copyToClipboard(format, filters = {}, options = {}) {
|
|
362
|
-
const result = this.export(format, filters, options);
|
|
363
|
-
try {
|
|
364
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
365
|
-
await navigator.clipboard.writeText(result.data);
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
// Fallback for non-secure contexts
|
|
370
|
-
const textArea = document.createElement('textarea');
|
|
371
|
-
textArea.value = result.data;
|
|
372
|
-
textArea.style.position = 'fixed';
|
|
373
|
-
textArea.style.opacity = '0';
|
|
374
|
-
document.body.appendChild(textArea);
|
|
375
|
-
textArea.focus();
|
|
376
|
-
textArea.select();
|
|
377
|
-
const success = document.execCommand('copy');
|
|
378
|
-
document.body.removeChild(textArea);
|
|
379
|
-
return success;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
console.error('Failed to copy to clipboard:', error);
|
|
384
|
-
return false;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Get all logs (for debugging)
|
|
389
|
-
*/
|
|
390
|
-
getAllLogs() {
|
|
391
|
-
return [...this.buffer];
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Save export to file with download prompt
|
|
395
|
-
*/
|
|
396
|
-
async saveToFile(format, filters = {}, options = {}) {
|
|
397
|
-
try {
|
|
398
|
-
const result = this.export(format, filters, options);
|
|
399
|
-
const blob = new Blob([result.data], {
|
|
400
|
-
type: this.getMimeType(format)
|
|
401
|
-
});
|
|
402
|
-
const url = URL.createObjectURL(blob);
|
|
403
|
-
const a = document.createElement('a');
|
|
404
|
-
const filename = this.generateFilename(format, filters);
|
|
405
|
-
a.href = url;
|
|
406
|
-
a.download = filename;
|
|
407
|
-
a.style.display = 'none';
|
|
408
|
-
document.body.appendChild(a);
|
|
409
|
-
a.click();
|
|
410
|
-
document.body.removeChild(a);
|
|
411
|
-
URL.revokeObjectURL(url);
|
|
412
|
-
return true;
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
console.error('Failed to save file:', error);
|
|
416
|
-
return false;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
/**
|
|
420
|
-
* Get MIME type for format
|
|
421
|
-
*/
|
|
422
|
-
getMimeType(format) {
|
|
423
|
-
const mimeTypes = {
|
|
424
|
-
json: 'application/json',
|
|
425
|
-
csv: 'text/csv',
|
|
426
|
-
markdown: 'text/markdown',
|
|
427
|
-
plain: 'text/plain',
|
|
428
|
-
html: 'text/html'
|
|
429
|
-
};
|
|
430
|
-
return mimeTypes[format] || 'text/plain';
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* Generate filename with timestamp
|
|
434
|
-
*/
|
|
435
|
-
generateFilename(format, filters) {
|
|
436
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
437
|
-
const prefix = filters.prefixes?.length === 1 ? `_${filters.prefixes[0]}` : '';
|
|
438
|
-
const extension = format === 'markdown' ? 'md' : format;
|
|
439
|
-
return `logs${prefix}_${timestamp}.${extension}`;
|
|
440
|
-
}
|
|
441
|
-
/**
|
|
442
|
-
* Stream logs to external endpoint
|
|
443
|
-
*/
|
|
444
|
-
async streamToEndpoint(endpoint, filters = {}, options = {}) {
|
|
445
|
-
try {
|
|
446
|
-
const logs = this.filterLogs(filters);
|
|
447
|
-
const batchSize = options.batchSize || 100;
|
|
448
|
-
const format = options.format || 'json';
|
|
449
|
-
// Send in batches
|
|
450
|
-
for (let i = 0; i < logs.length; i += batchSize) {
|
|
451
|
-
const batch = logs.slice(i, i + batchSize);
|
|
452
|
-
const result = this.export(format, {}, { compact: true });
|
|
453
|
-
const headers = {
|
|
454
|
-
'Content-Type': 'application/json'
|
|
455
|
-
};
|
|
456
|
-
if (options.apiKey) {
|
|
457
|
-
headers['Authorization'] = `Bearer ${options.apiKey}`;
|
|
458
|
-
}
|
|
459
|
-
const response = await fetch(endpoint, {
|
|
460
|
-
method: 'POST',
|
|
461
|
-
headers,
|
|
462
|
-
body: JSON.stringify({
|
|
463
|
-
logs: batch,
|
|
464
|
-
metadata: {
|
|
465
|
-
batchIndex: Math.floor(i / batchSize),
|
|
466
|
-
totalBatches: Math.ceil(logs.length / batchSize),
|
|
467
|
-
timestamp: new Date().toISOString()
|
|
468
|
-
}
|
|
469
|
-
})
|
|
470
|
-
});
|
|
471
|
-
if (!response.ok) {
|
|
472
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
return true;
|
|
476
|
-
}
|
|
477
|
-
catch (error) {
|
|
478
|
-
console.error('Failed to stream logs:', error);
|
|
479
|
-
return false;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Create export with metadata enrichment
|
|
484
|
-
*/
|
|
485
|
-
exportWithMetadata(format, filters = {}, options = {}) {
|
|
486
|
-
const baseResult = this.export(format, filters, options);
|
|
487
|
-
const bufferStats = this.getBufferStats();
|
|
488
|
-
return {
|
|
489
|
-
...baseResult,
|
|
490
|
-
metadata: {
|
|
491
|
-
...baseResult.metadata,
|
|
492
|
-
bufferStats: bufferStats,
|
|
493
|
-
performance: {
|
|
494
|
-
memoryUsage: this.estimateMemoryUsage(),
|
|
495
|
-
processingTime: Date.now()
|
|
496
|
-
},
|
|
497
|
-
system: {
|
|
498
|
-
userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Node.js',
|
|
499
|
-
timestamp: new Date().toISOString(),
|
|
500
|
-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Estimate memory usage of buffer
|
|
507
|
-
*/
|
|
508
|
-
estimateMemoryUsage() {
|
|
509
|
-
const sampleEntry = this.buffer[0];
|
|
510
|
-
if (!sampleEntry)
|
|
511
|
-
return 0;
|
|
512
|
-
// Rough estimation: JSON.stringify size * buffer length
|
|
513
|
-
const sampleSize = JSON.stringify(sampleEntry).length;
|
|
514
|
-
return sampleSize * this.buffer.length;
|
|
515
|
-
}
|
|
516
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview File-based log handler for Advanced Logger
|
|
3
|
-
*/
|
|
4
|
-
import type { ILogHandler, LogLevel, LogMetadata } from '../types/index.js';
|
|
5
|
-
/**
|
|
6
|
-
* Universal file-based log handler for persistent logging
|
|
7
|
-
* Works in both Node.js (real files) and browser (localStorage)
|
|
8
|
-
*/
|
|
9
|
-
export declare class FileLogHandler implements ILogHandler {
|
|
10
|
-
private filename;
|
|
11
|
-
private maxSize?;
|
|
12
|
-
private fs?;
|
|
13
|
-
constructor(filename?: string, maxSize?: number);
|
|
14
|
-
handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): void;
|
|
15
|
-
/**
|
|
16
|
-
* Format log entry as a single line for file storage
|
|
17
|
-
*/
|
|
18
|
-
private formatLogLine;
|
|
19
|
-
/**
|
|
20
|
-
* Write to actual file in Node.js environment
|
|
21
|
-
*/
|
|
22
|
-
private writeToFileNode;
|
|
23
|
-
/**
|
|
24
|
-
* Write to localStorage in browser environment
|
|
25
|
-
*/
|
|
26
|
-
private writeToFileLocal;
|
|
27
|
-
/**
|
|
28
|
-
* Get stored logs (useful for debugging)
|
|
29
|
-
*/
|
|
30
|
-
getLogs(): string | null;
|
|
31
|
-
/**
|
|
32
|
-
* Clear stored logs
|
|
33
|
-
*/
|
|
34
|
-
clearLogs(): void;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=FileLogHandler.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FileLogHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/FileLogHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI5E;;;GAGG;AACH,qBAAa,cAAe,YAAW,WAAW;IAC9C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,EAAE,CAAC,CAAM;gBAEL,QAAQ,GAAE,MAAkB,EAAE,OAAO,CAAC,EAAE,MAAM;IAc1D,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,WAAW,GAAG,IAAI;IAsBlF;;OAEG;IACH,OAAO,CAAC,aAAa;IAuBrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;OAEG;IACH,OAAO,IAAI,MAAM,GAAG,IAAI;IAcxB;;OAEG;IACH,SAAS,IAAI,IAAI;CAYpB"}
|