@mks2508/better-logger 0.0.1 → 0.0.2-alpha.2

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 (64) hide show
  1. package/.claude/settings.local.json +10 -1
  2. package/.github/workflows/ci.yml +319 -0
  3. package/.github/workflows/release.yml +269 -0
  4. package/.npmrc.bak +1 -0
  5. package/README.md +577 -0
  6. package/demo.html +840 -0
  7. package/dist/chunks/Logger-BQhMKy_T.js +2 -0
  8. package/dist/chunks/Logger-BQhMKy_T.js.map +1 -0
  9. package/dist/chunks/Logger-BrFKFZcD.js +978 -0
  10. package/dist/chunks/Logger-BrFKFZcD.js.map +1 -0
  11. package/dist/chunks/core-2opW4Pi3.js +194 -0
  12. package/dist/chunks/core-2opW4Pi3.js.map +1 -0
  13. package/dist/chunks/core-DyugwSYZ.js +4 -0
  14. package/dist/chunks/core-DyugwSYZ.js.map +1 -0
  15. package/dist/chunks/exports-BNP3R7dp.js +421 -0
  16. package/dist/chunks/exports-BNP3R7dp.js.map +1 -0
  17. package/dist/chunks/exports-U1xLBXrY.js +2 -0
  18. package/dist/chunks/exports-U1xLBXrY.js.map +1 -0
  19. package/dist/chunks/styling-DhUDzwlE.js +654 -0
  20. package/dist/chunks/styling-DhUDzwlE.js.map +1 -0
  21. package/dist/chunks/styling-tmRDI28D.js +2 -0
  22. package/dist/chunks/styling-tmRDI28D.js.map +1 -0
  23. package/dist/core.cjs +2 -0
  24. package/dist/core.cjs.map +1 -0
  25. package/dist/core.js +244 -0
  26. package/dist/core.js.map +1 -0
  27. package/dist/exports.cjs +2 -0
  28. package/dist/exports.cjs.map +1 -0
  29. package/dist/exports.js +237 -0
  30. package/dist/exports.js.map +1 -0
  31. package/dist/index.cjs +2 -0
  32. package/dist/index.cjs.map +1 -0
  33. package/dist/index.js +105 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/styling.cjs +2 -0
  36. package/dist/styling.cjs.map +1 -0
  37. package/dist/styling.js +146 -0
  38. package/dist/styling.js.map +1 -0
  39. package/dist/types/core.d.ts +211 -0
  40. package/dist/types/exports.d.ts +600 -0
  41. package/dist/types/index.d.ts +675 -0
  42. package/dist/types/styling.d.ts +751 -0
  43. package/docs/CORE.md +264 -0
  44. package/docs/EXPORTS.md +467 -0
  45. package/docs/STYLING.md +405 -0
  46. package/index.html +28 -4
  47. package/package.json +37 -4
  48. package/src/Logger.ts +28 -8
  49. package/src/cli/CommandProcessor.ts +2 -2
  50. package/src/cli/commands/ExportCommand.ts +5 -0
  51. package/src/cli/commands/StatusCommand.ts +11 -10
  52. package/src/core.ts +320 -0
  53. package/src/example.ts +184 -62
  54. package/src/exports-module.ts +311 -0
  55. package/src/handlers/ExportLogHandler.ts +34 -13
  56. package/src/index.ts +97 -79
  57. package/src/main.ts +77 -7
  58. package/src/styling-module.ts +244 -0
  59. package/src/utils/stackTrace.ts +39 -10
  60. package/src/utils/timestamps.ts +1 -1
  61. package/tsconfig.json +40 -14
  62. package/vite.config.ts +84 -0
  63. package/dist/assets/index-DxvJByYN.js +0 -183
  64. package/dist/index.html +0 -334
@@ -0,0 +1,421 @@
1
+ import { B as BUFFER_LIMITS, g as generateLogId, p as parseTimeInput, f as formatDisplayTime, s as safeStringify, e as escapeHtml } from "./core-2opW4Pi3.js";
2
+ class RemoteLogHandler {
3
+ endpoint;
4
+ apiKey;
5
+ constructor(endpoint, apiKey) {
6
+ this.endpoint = endpoint;
7
+ this.apiKey = apiKey;
8
+ }
9
+ async handle(level, message, args, metadata) {
10
+ try {
11
+ const payload = {
12
+ timestamp: metadata.timestamp,
13
+ level,
14
+ message,
15
+ prefix: metadata.prefix,
16
+ location: metadata.stackInfo,
17
+ additional: args.slice(1)
18
+ };
19
+ await fetch(this.endpoint, {
20
+ method: "POST",
21
+ headers: {
22
+ "Content-Type": "application/json",
23
+ ...this.apiKey && { "Authorization": `Bearer ${this.apiKey}` }
24
+ },
25
+ body: JSON.stringify(payload)
26
+ });
27
+ } catch (error) {
28
+ }
29
+ }
30
+ }
31
+ class ExportLogHandler {
32
+ buffer = [];
33
+ maxSize;
34
+ groupDepth = 0;
35
+ currentGroup;
36
+ constructor(maxSize = BUFFER_LIMITS.DEFAULT_SIZE) {
37
+ this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
38
+ }
39
+ /**
40
+ * Handle incoming log and store in buffer
41
+ */
42
+ handle(level, message, args, metadata) {
43
+ const entry = {
44
+ id: generateLogId(),
45
+ timestamp: metadata.timestamp,
46
+ level,
47
+ prefix: metadata.prefix,
48
+ message,
49
+ args,
50
+ location: metadata.stackInfo,
51
+ groupInfo: this.groupDepth > 0 ? {
52
+ depth: this.groupDepth,
53
+ groupName: this.currentGroup
54
+ } : void 0
55
+ };
56
+ this.buffer.push(entry);
57
+ if (this.buffer.length > this.maxSize) {
58
+ this.buffer.shift();
59
+ }
60
+ }
61
+ /**
62
+ * Set group tracking for nested logs
63
+ */
64
+ setGroupInfo(depth, groupName) {
65
+ this.groupDepth = depth;
66
+ this.currentGroup = groupName;
67
+ }
68
+ /**
69
+ * Get buffer statistics
70
+ */
71
+ getBufferStats() {
72
+ const levelCounts = this.buffer.reduce((acc, entry) => {
73
+ const currentCount = acc[entry.level] ? acc[entry.level] : 0;
74
+ acc[entry.level] = currentCount + 1;
75
+ return acc;
76
+ }, {});
77
+ let oldestLog;
78
+ let newestLog;
79
+ if (this.buffer.length > 0) {
80
+ const firstEntry = this.buffer[0];
81
+ const lastEntry = this.buffer[this.buffer.length - 1];
82
+ if (firstEntry && firstEntry.timestamp) {
83
+ oldestLog = new Date(firstEntry.timestamp);
84
+ }
85
+ if (lastEntry && lastEntry.timestamp) {
86
+ newestLog = new Date(lastEntry.timestamp);
87
+ }
88
+ }
89
+ return {
90
+ size: this.buffer.length,
91
+ maxSize: this.maxSize,
92
+ usage: this.buffer.length / this.maxSize * 100,
93
+ oldestLog,
94
+ newestLog,
95
+ levelCounts: {
96
+ debug: levelCounts.debug ? levelCounts.debug : 0,
97
+ info: levelCounts.info ? levelCounts.info : 0,
98
+ warn: levelCounts.warn ? levelCounts.warn : 0,
99
+ error: levelCounts.error ? levelCounts.error : 0,
100
+ critical: levelCounts.critical ? levelCounts.critical : 0
101
+ }
102
+ };
103
+ }
104
+ /**
105
+ * Clear the buffer
106
+ */
107
+ clearBuffer() {
108
+ this.buffer = [];
109
+ }
110
+ /**
111
+ * Set buffer size (with limits)
112
+ */
113
+ setBufferSize(size) {
114
+ this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
115
+ if (this.buffer.length > this.maxSize) {
116
+ this.buffer = this.buffer.slice(-this.maxSize);
117
+ }
118
+ }
119
+ /**
120
+ * Filter logs based on criteria
121
+ */
122
+ filterLogs(filters = {}) {
123
+ let filtered = [...this.buffer];
124
+ if (filters.levels?.length) {
125
+ filtered = filtered.filter((entry) => filters.levels.includes(entry.level));
126
+ }
127
+ if (filters.prefixes?.length) {
128
+ filtered = filtered.filter(
129
+ (entry) => entry.prefix && filters.prefixes.includes(entry.prefix)
130
+ );
131
+ }
132
+ if (filters.excludePrefixes?.length) {
133
+ filtered = filtered.filter(
134
+ (entry) => !entry.prefix || !filters.excludePrefixes.includes(entry.prefix)
135
+ );
136
+ }
137
+ if (filters.since) {
138
+ const sinceDate = parseTimeInput(filters.since);
139
+ filtered = filtered.filter((entry) => new Date(entry.timestamp) >= sinceDate);
140
+ }
141
+ if (filters.until) {
142
+ const untilDate = parseTimeInput(filters.until);
143
+ filtered = filtered.filter((entry) => new Date(entry.timestamp) <= untilDate);
144
+ }
145
+ if (filters.withStackTrace) {
146
+ filtered = filtered.filter((entry) => entry.location);
147
+ }
148
+ if (filters.errorsOnly) {
149
+ filtered = filtered.filter((entry) => entry.level === "error" || entry.level === "critical");
150
+ }
151
+ if (filters.search) {
152
+ const searchTerm = filters.search.toLowerCase();
153
+ filtered = filtered.filter(
154
+ (entry) => entry.message.toLowerCase().includes(searchTerm) || entry.args.some(
155
+ (arg) => String(arg).toLowerCase().includes(searchTerm)
156
+ )
157
+ );
158
+ }
159
+ if (filters.last) {
160
+ filtered = filtered.slice(-filters.last);
161
+ }
162
+ if (filters.first) {
163
+ filtered = filtered.slice(0, filters.first);
164
+ }
165
+ return filtered;
166
+ }
167
+ /**
168
+ * Export logs in JSON format
169
+ */
170
+ exportJSON(logs, options) {
171
+ const data = logs.map((entry) => ({
172
+ timestamp: entry.timestamp,
173
+ level: entry.level,
174
+ prefix: entry.prefix,
175
+ message: entry.message,
176
+ ...options.minimal ? {} : {
177
+ args: entry.args.slice(1),
178
+ location: entry.location,
179
+ groupInfo: entry.groupInfo
180
+ }
181
+ }));
182
+ return options.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);
183
+ }
184
+ /**
185
+ * Export logs in CSV format
186
+ */
187
+ exportCSV(logs, options) {
188
+ const headers = options.minimal ? ["Timestamp", "Level", "Prefix", "Message"] : ["Timestamp", "Level", "Prefix", "Message", "File", "Line", "Args"];
189
+ const rows = logs.map((entry) => {
190
+ const baseRow = [
191
+ formatDisplayTime(new Date(entry.timestamp), "full"),
192
+ entry.level.toUpperCase(),
193
+ entry.prefix || "",
194
+ `"${entry.message.replace(/"/g, '""')}"`
195
+ ];
196
+ if (!options.minimal) {
197
+ baseRow.push(
198
+ entry.location?.file || "",
199
+ entry.location?.line?.toString() || "",
200
+ `"${safeStringify(entry.args.slice(1)).replace(/"/g, '""')}"`
201
+ );
202
+ }
203
+ return baseRow;
204
+ });
205
+ return [headers.join(","), ...rows.map((row) => row.join(","))].join("\n");
206
+ }
207
+ /**
208
+ * Export logs in Markdown format
209
+ */
210
+ exportMarkdown(logs, options) {
211
+ const now = /* @__PURE__ */ new Date();
212
+ let content = `# Log Export - ${formatDisplayTime(now, "full")}
213
+
214
+ `;
215
+ if (!options.minimal) {
216
+ const summary = this.getBufferStats();
217
+ content += `## Summary
218
+ `;
219
+ content += `- **Total logs**: ${logs.length}
220
+ `;
221
+ content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}
222
+ `;
223
+ content += `- **Warnings**: ${summary.levelCounts.warn}
224
+
225
+ `;
226
+ }
227
+ if (options.groupBy === "level") {
228
+ const grouped = logs.reduce((acc, entry) => {
229
+ const level = entry.level;
230
+ if (!acc[level]) {
231
+ acc[level] = [];
232
+ }
233
+ const levelArray = acc[level];
234
+ if (levelArray) {
235
+ levelArray.push(entry);
236
+ }
237
+ return acc;
238
+ }, {});
239
+ Object.entries(grouped).forEach(([level, entries]) => {
240
+ const emoji = this.getLevelEmoji(level);
241
+ content += `## ${emoji} ${level.toUpperCase()} (${entries.length})
242
+
243
+ `;
244
+ entries.forEach((entry) => {
245
+ const time = formatDisplayTime(new Date(entry.timestamp), "time-only");
246
+ const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
247
+ const prefix = entry.prefix ? ` **${entry.prefix}**:` : "";
248
+ content += `- \`${time}\`${prefix} ${entry.message}${location}
249
+ `;
250
+ });
251
+ content += "\n";
252
+ });
253
+ } else {
254
+ content += "## Logs\n\n";
255
+ logs.forEach((entry) => {
256
+ const time = formatDisplayTime(new Date(entry.timestamp), "time-only");
257
+ const emoji = this.getLevelEmoji(entry.level);
258
+ const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
259
+ const prefix = entry.prefix ? ` **${entry.prefix}**:` : "";
260
+ content += `- \`${time}\` ${emoji}${prefix} ${entry.message}${location}
261
+ `;
262
+ });
263
+ }
264
+ return content;
265
+ }
266
+ /**
267
+ * Export logs in plain text format
268
+ */
269
+ exportPlain(logs, options) {
270
+ return logs.map((entry) => {
271
+ const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? "time-only" : "short");
272
+ const level = entry.level.toUpperCase().padEnd(8);
273
+ const prefix = entry.prefix ? `[${entry.prefix}] ` : "";
274
+ const location = !options.minimal && entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
275
+ return `${time} ${level} ${prefix}${entry.message}${location}`;
276
+ }).join("\n");
277
+ }
278
+ /**
279
+ * Export logs in HTML format
280
+ */
281
+ exportHTML(logs, _options) {
282
+ const title = `Log Export - ${formatDisplayTime(/* @__PURE__ */ new Date(), "full")}`;
283
+ let html = `<!DOCTYPE html>
284
+ <html lang="en">
285
+ <head>
286
+ <meta charset="UTF-8">
287
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
288
+ <title>${title}</title>
289
+ <style>
290
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }
291
+ .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }
292
+ .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }
293
+ .timestamp { color: #666; font-size: 0.9em; }
294
+ .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
295
+ .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
296
+ .location { color: #718096; font-size: 0.9em; }
297
+ .debug { background: #f0f4ff; }
298
+ .info { background: #f0f9ff; }
299
+ .warn { background: #fffbeb; }
300
+ .error { background: #fef2f2; }
301
+ .critical { background: #fef2f2; border-left: 4px solid #dc2626; }
302
+ .level.debug { background: #667eea; color: white; }
303
+ .level.info { background: #74b9ff; color: white; }
304
+ .level.warn { background: #fdcb6e; color: #2d3436; }
305
+ .level.error { background: #e84393; color: white; }
306
+ .level.critical { background: #ff3838; color: white; }
307
+ </style>
308
+ </head>
309
+ <body>
310
+ <div class="header">
311
+ <h1>${title}</h1>
312
+ <p>Generated by Advanced Logger v2.0.0</p>
313
+ </div>
314
+ <div class="logs">`;
315
+ logs.forEach((entry) => {
316
+ const time = formatDisplayTime(new Date(entry.timestamp), "full");
317
+ const location = entry.location ? ` <span class="location">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : "";
318
+ const prefix = entry.prefix ? ` <span class="prefix">${escapeHtml(entry.prefix)}</span>` : "";
319
+ html += `
320
+ <div class="log-entry ${entry.level}">
321
+ <span class="timestamp">${time}</span>
322
+ <span class="level ${entry.level}">${entry.level.toUpperCase()}</span>
323
+ ${prefix}
324
+ <span class="message">${escapeHtml(entry.message)}</span>
325
+ ${location}
326
+ </div>`;
327
+ });
328
+ html += `
329
+ </div>
330
+ </body>
331
+ </html>`;
332
+ return html;
333
+ }
334
+ /**
335
+ * Get emoji for log level
336
+ */
337
+ getLevelEmoji(level) {
338
+ const emojis = {
339
+ debug: "🐞",
340
+ info: "â„šī¸",
341
+ warn: "âš ī¸",
342
+ error: "❌",
343
+ critical: "đŸ”Ĩ"
344
+ };
345
+ return emojis[level] || "";
346
+ }
347
+ /**
348
+ * Main export function
349
+ */
350
+ export(format, filters = {}, options = {}) {
351
+ const filteredLogs = this.filterLogs(filters);
352
+ let data;
353
+ switch (format) {
354
+ case "json":
355
+ data = this.exportJSON(filteredLogs, options);
356
+ break;
357
+ case "csv":
358
+ data = this.exportCSV(filteredLogs, options);
359
+ break;
360
+ case "markdown":
361
+ data = this.exportMarkdown(filteredLogs, options);
362
+ break;
363
+ case "plain":
364
+ data = this.exportPlain(filteredLogs, options);
365
+ break;
366
+ case "html":
367
+ data = this.exportHTML(filteredLogs, options);
368
+ break;
369
+ default:
370
+ throw new Error(`Unsupported export format: ${format}`);
371
+ }
372
+ return {
373
+ format,
374
+ data,
375
+ metadata: {
376
+ totalLogs: this.buffer.length,
377
+ filteredLogs: filteredLogs.length,
378
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
379
+ filters,
380
+ options
381
+ }
382
+ };
383
+ }
384
+ /**
385
+ * Copy to clipboard with fallback
386
+ */
387
+ async copyToClipboard(format, filters = {}, options = {}) {
388
+ const result = this.export(format, filters, options);
389
+ try {
390
+ if (navigator.clipboard && window.isSecureContext) {
391
+ await navigator.clipboard.writeText(result.data);
392
+ return true;
393
+ } else {
394
+ const textArea = document.createElement("textarea");
395
+ textArea.value = result.data;
396
+ textArea.style.position = "fixed";
397
+ textArea.style.opacity = "0";
398
+ document.body.appendChild(textArea);
399
+ textArea.focus();
400
+ textArea.select();
401
+ const success = document.execCommand("copy");
402
+ document.body.removeChild(textArea);
403
+ return success;
404
+ }
405
+ } catch (error) {
406
+ console.error("Failed to copy to clipboard:", error);
407
+ return false;
408
+ }
409
+ }
410
+ /**
411
+ * Get all logs (for debugging)
412
+ */
413
+ getAllLogs() {
414
+ return [...this.buffer];
415
+ }
416
+ }
417
+ export {
418
+ ExportLogHandler as E,
419
+ RemoteLogHandler as R
420
+ };
421
+ //# sourceMappingURL=exports-BNP3R7dp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exports-BNP3R7dp.js","sources":["../../src/handlers/RemoteLogHandler.ts","../../src/handlers/ExportLogHandler.ts"],"sourcesContent":["/**\n * @fileoverview Remote log handler for Advanced Logger\n */\n\nimport type { ILogHandler, LogLevel, LogMetadata } from '../types/index.js';\n\n/**\n * Remote log handler for sending logs to external services\n */\nexport class RemoteLogHandler implements ILogHandler {\n private endpoint: string;\n private apiKey?: string;\n\n constructor(endpoint: string, apiKey?: string) {\n this.endpoint = endpoint;\n this.apiKey = apiKey;\n }\n\n async handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): Promise<void> {\n try {\n const payload = {\n timestamp: metadata.timestamp,\n level,\n message,\n prefix: metadata.prefix,\n location: metadata.stackInfo,\n additional: args.slice(1),\n };\n\n await fetch(this.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.apiKey && { 'Authorization': `Bearer ${this.apiKey}` }),\n },\n body: JSON.stringify(payload),\n });\n } catch (error) {\n // Silently fail to avoid infinite logging loops\n }\n }\n}","/**\n * @fileoverview Export and clipboard log handler for Advanced Logger\n */\n\nimport type { \n ILogHandler, \n LogLevel, \n LogMetadata, \n LogEntry, \n ExportFilters, \n ExportOptions, \n ExportResult, \n BufferStats,\n ExportFormat\n} from '../types/index.js';\nimport { parseTimeInput, formatDisplayTime, safeStringify, escapeHtml, generateLogId } from '../utils/index.js';\nimport { BUFFER_LIMITS } from '../constants.js';\n\n/**\n * Export log handler with circular buffer and multiple export formats\n */\nexport class ExportLogHandler implements ILogHandler {\n private buffer: LogEntry[] = [];\n private maxSize: number;\n private groupDepth: number = 0;\n private currentGroup?: string;\n\n constructor(maxSize: number = BUFFER_LIMITS.DEFAULT_SIZE) {\n this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);\n }\n\n /**\n * Handle incoming log and store in buffer\n */\n handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): void {\n const entry: LogEntry = {\n id: generateLogId(),\n timestamp: metadata.timestamp,\n level,\n prefix: metadata.prefix,\n message,\n args,\n location: metadata.stackInfo,\n groupInfo: this.groupDepth > 0 ? {\n depth: this.groupDepth,\n groupName: this.currentGroup\n } : undefined\n };\n\n // Add to circular buffer\n this.buffer.push(entry);\n if (this.buffer.length > this.maxSize) {\n this.buffer.shift(); // Remove oldest entry\n }\n }\n\n /**\n * Set group tracking for nested logs\n */\n setGroupInfo(depth: number, groupName?: string): void {\n this.groupDepth = depth;\n this.currentGroup = groupName;\n }\n\n /**\n * Get buffer statistics\n */\n getBufferStats(): BufferStats {\n const levelCounts = this.buffer.reduce((acc, entry) => {\n const currentCount = acc[entry.level] ? acc[entry.level] : 0;\n acc[entry.level] = currentCount + 1;\n return acc;\n }, {} as Record<LogLevel, number>);\n\n let oldestLog: Date | undefined;\n let newestLog: Date | undefined;\n \n if (this.buffer.length > 0) {\n const firstEntry = this.buffer[0];\n const lastEntry = this.buffer[this.buffer.length - 1];\n \n if (firstEntry && firstEntry.timestamp) {\n oldestLog = new Date(firstEntry.timestamp);\n }\n \n if (lastEntry && lastEntry.timestamp) {\n newestLog = new Date(lastEntry.timestamp);\n }\n }\n\n return {\n size: this.buffer.length,\n maxSize: this.maxSize,\n usage: (this.buffer.length / this.maxSize) * 100,\n oldestLog,\n newestLog,\n levelCounts: {\n debug: levelCounts.debug ? levelCounts.debug : 0,\n info: levelCounts.info ? levelCounts.info : 0,\n warn: levelCounts.warn ? levelCounts.warn : 0,\n error: levelCounts.error ? levelCounts.error : 0,\n critical: levelCounts.critical ? levelCounts.critical : 0\n }\n };\n }\n\n /**\n * Clear the buffer\n */\n clearBuffer(): void {\n this.buffer = [];\n }\n\n /**\n * Set buffer size (with limits)\n */\n setBufferSize(size: number): void {\n this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);\n \n // Trim buffer if new size is smaller\n if (this.buffer.length > this.maxSize) {\n this.buffer = this.buffer.slice(-this.maxSize);\n }\n }\n\n /**\n * Filter logs based on criteria\n */\n private filterLogs(filters: ExportFilters = {}): LogEntry[] {\n let filtered = [...this.buffer];\n\n // Filter by levels\n if (filters.levels?.length) {\n filtered = filtered.filter(entry => filters.levels!.includes(entry.level));\n }\n\n // Filter by prefixes\n if (filters.prefixes?.length) {\n filtered = filtered.filter(entry => \n entry.prefix && filters.prefixes!.includes(entry.prefix)\n );\n }\n\n // Exclude prefixes\n if (filters.excludePrefixes?.length) {\n filtered = filtered.filter(entry => \n !entry.prefix || !filters.excludePrefixes!.includes(entry.prefix)\n );\n }\n\n // Filter by time range\n if (filters.since) {\n const sinceDate = parseTimeInput(filters.since);\n filtered = filtered.filter(entry => new Date(entry.timestamp) >= sinceDate);\n }\n\n if (filters.until) {\n const untilDate = parseTimeInput(filters.until);\n filtered = filtered.filter(entry => new Date(entry.timestamp) <= untilDate);\n }\n\n // Filter by stack trace presence\n if (filters.withStackTrace) {\n filtered = filtered.filter(entry => entry.location);\n }\n\n // Filter errors only\n if (filters.errorsOnly) {\n filtered = filtered.filter(entry => entry.level === 'error' || entry.level === 'critical');\n }\n\n // Search in messages\n if (filters.search) {\n const searchTerm = filters.search.toLowerCase();\n filtered = filtered.filter(entry => \n entry.message.toLowerCase().includes(searchTerm) ||\n entry.args.some(arg => \n String(arg).toLowerCase().includes(searchTerm)\n )\n );\n }\n\n // Limit results\n if (filters.last) {\n filtered = filtered.slice(-filters.last);\n }\n\n if (filters.first) {\n filtered = filtered.slice(0, filters.first);\n }\n\n return filtered;\n }\n\n /**\n * Export logs in JSON format\n */\n private exportJSON(logs: LogEntry[], options: ExportOptions): string {\n const data = logs.map(entry => ({\n timestamp: entry.timestamp,\n level: entry.level,\n prefix: entry.prefix,\n message: entry.message,\n ...(options.minimal ? {} : {\n args: entry.args.slice(1),\n location: entry.location,\n groupInfo: entry.groupInfo\n })\n }));\n\n return options.compact \n ? JSON.stringify(data)\n : JSON.stringify(data, null, 2);\n }\n\n /**\n * Export logs in CSV format\n */\n private exportCSV(logs: LogEntry[], options: ExportOptions): string {\n const headers = options.minimal \n ? ['Timestamp', 'Level', 'Prefix', 'Message']\n : ['Timestamp', 'Level', 'Prefix', 'Message', 'File', 'Line', 'Args'];\n\n const rows = logs.map(entry => {\n const baseRow = [\n formatDisplayTime(new Date(entry.timestamp), 'full'),\n entry.level.toUpperCase(),\n entry.prefix || '',\n `\"${entry.message.replace(/\"/g, '\"\"')}\"`\n ];\n\n if (!options.minimal) {\n baseRow.push(\n entry.location?.file || '',\n entry.location?.line?.toString() || '',\n `\"${safeStringify(entry.args.slice(1)).replace(/\"/g, '\"\"')}\"`\n );\n }\n\n return baseRow;\n });\n\n return [headers.join(','), ...rows.map(row => row.join(','))].join('\\n');\n }\n\n /**\n * Export logs in Markdown format\n */\n private exportMarkdown(logs: LogEntry[], options: ExportOptions): string {\n const now = new Date();\n let content = `# Log Export - ${formatDisplayTime(now, 'full')}\\n\\n`;\n\n // Add summary if not minimal\n if (!options.minimal) {\n const summary = this.getBufferStats();\n content += `## Summary\\n`;\n content += `- **Total logs**: ${logs.length}\\n`;\n content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}\\n`;\n content += `- **Warnings**: ${summary.levelCounts.warn}\\n\\n`;\n }\n\n // Group by level if specified\n if (options.groupBy === 'level') {\n const grouped = logs.reduce((acc, entry) => {\n const level = entry.level;\n if (!acc[level]) {\n acc[level] = [];\n }\n // We just ensured the array exists above\n const levelArray = acc[level];\n if (levelArray) {\n levelArray.push(entry);\n }\n return acc;\n }, {} as Record<string, LogEntry[]>);\n\n Object.entries(grouped).forEach(([level, entries]) => {\n const emoji = this.getLevelEmoji(level as LogLevel);\n content += `## ${emoji} ${level.toUpperCase()} (${entries.length})\\n\\n`;\n \n entries.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');\n const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';\n const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';\n content += `- \\`${time}\\`${prefix} ${entry.message}${location}\\n`;\n });\n content += '\\n';\n });\n } else {\n content += '## Logs\\n\\n';\n logs.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');\n const emoji = this.getLevelEmoji(entry.level);\n const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';\n const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';\n content += `- \\`${time}\\` ${emoji}${prefix} ${entry.message}${location}\\n`;\n });\n }\n\n return content;\n }\n\n /**\n * Export logs in plain text format\n */\n private exportPlain(logs: LogEntry[], options: ExportOptions): string {\n return logs.map(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? 'time-only' : 'short');\n const level = entry.level.toUpperCase().padEnd(8);\n const prefix = entry.prefix ? `[${entry.prefix}] ` : '';\n const location = (!options.minimal && entry.location) ? ` (${entry.location.file}:${entry.location.line})` : '';\n \n return `${time} ${level} ${prefix}${entry.message}${location}`;\n }).join('\\n');\n }\n\n /**\n * Export logs in HTML format\n */\n private exportHTML(logs: LogEntry[], _options: ExportOptions): string {\n const title = `Log Export - ${formatDisplayTime(new Date(), 'full')}`;\n \n let html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title}</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }\n .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }\n .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }\n .timestamp { color: #666; font-size: 0.9em; }\n .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .location { color: #718096; font-size: 0.9em; }\n .debug { background: #f0f4ff; }\n .info { background: #f0f9ff; }\n .warn { background: #fffbeb; }\n .error { background: #fef2f2; }\n .critical { background: #fef2f2; border-left: 4px solid #dc2626; }\n .level.debug { background: #667eea; color: white; }\n .level.info { background: #74b9ff; color: white; }\n .level.warn { background: #fdcb6e; color: #2d3436; }\n .level.error { background: #e84393; color: white; }\n .level.critical { background: #ff3838; color: white; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>${title}</h1>\n <p>Generated by Advanced Logger v2.0.0</p>\n </div>\n <div class=\"logs\">`;\n\n logs.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'full');\n const location = entry.location ? ` <span class=\"location\">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : '';\n const prefix = entry.prefix ? ` <span class=\"prefix\">${escapeHtml(entry.prefix)}</span>` : '';\n \n html += `\n <div class=\"log-entry ${entry.level}\">\n <span class=\"timestamp\">${time}</span>\n <span class=\"level ${entry.level}\">${entry.level.toUpperCase()}</span>\n ${prefix}\n <span class=\"message\">${escapeHtml(entry.message)}</span>\n ${location}\n </div>`;\n });\n\n html += `\n </div>\n</body>\n</html>`;\n\n return html;\n }\n\n /**\n * Get emoji for log level\n */\n private getLevelEmoji(level: LogLevel): string {\n const emojis = {\n debug: '🐞',\n info: 'â„šī¸',\n warn: 'âš ī¸',\n error: '❌',\n critical: 'đŸ”Ĩ'\n };\n return emojis[level] || '';\n }\n\n /**\n * Main export function\n */\n export(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): ExportResult {\n const filteredLogs = this.filterLogs(filters);\n \n let data: string;\n switch (format) {\n case 'json':\n data = this.exportJSON(filteredLogs, options);\n break;\n case 'csv':\n data = this.exportCSV(filteredLogs, options);\n break;\n case 'markdown':\n data = this.exportMarkdown(filteredLogs, options);\n break;\n case 'plain':\n data = this.exportPlain(filteredLogs, options);\n break;\n case 'html':\n data = this.exportHTML(filteredLogs, options);\n break;\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n\n return {\n format,\n data,\n metadata: {\n totalLogs: this.buffer.length,\n filteredLogs: filteredLogs.length,\n exportedAt: new Date().toISOString(),\n filters,\n options\n }\n };\n }\n\n /**\n * Copy to clipboard with fallback\n */\n async copyToClipboard(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): Promise<boolean> {\n const result = this.export(format, filters, options);\n \n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(result.data);\n return true;\n } else {\n // Fallback for non-secure contexts\n const textArea = document.createElement('textarea');\n textArea.value = result.data;\n textArea.style.position = 'fixed';\n textArea.style.opacity = '0';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n const success = document.execCommand('copy');\n document.body.removeChild(textArea);\n return success;\n }\n } catch (error) {\n console.error('Failed to copy to clipboard:', error);\n return false;\n }\n }\n\n /**\n * Get all logs (for debugging)\n */\n getAllLogs(): LogEntry[] {\n return [...this.buffer];\n }\n}"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const e=require("./core-DyugwSYZ.js");exports.ExportLogHandler=class{buffer=[];maxSize;groupDepth=0;currentGroup;constructor(t=e.BUFFER_LIMITS.DEFAULT_SIZE){this.maxSize=Math.min(Math.max(t,e.BUFFER_LIMITS.MIN_SIZE),e.BUFFER_LIMITS.MAX_SIZE)}handle(t,i,r,n){const o={id:e.generateLogId(),timestamp:n.timestamp,level:t,prefix:n.prefix,message:i,args:r,location:n.stackInfo,groupInfo:this.groupDepth>0?{depth:this.groupDepth,groupName:this.currentGroup}:void 0};this.buffer.push(o),this.buffer.length>this.maxSize&&this.buffer.shift()}setGroupInfo(e,t){this.groupDepth=e,this.currentGroup=t}getBufferStats(){const e=this.buffer.reduce((e,t)=>{const i=e[t.level]?e[t.level]:0;return e[t.level]=i+1,e},{});let t,i;if(this.buffer.length>0){const e=this.buffer[0],r=this.buffer[this.buffer.length-1];e&&e.timestamp&&(t=new Date(e.timestamp)),r&&r.timestamp&&(i=new Date(r.timestamp))}return{size:this.buffer.length,maxSize:this.maxSize,usage:this.buffer.length/this.maxSize*100,oldestLog:t,newestLog:i,levelCounts:{debug:e.debug?e.debug:0,info:e.info?e.info:0,warn:e.warn?e.warn:0,error:e.error?e.error:0,critical:e.critical?e.critical:0}}}clearBuffer(){this.buffer=[]}setBufferSize(t){this.maxSize=Math.min(Math.max(t,e.BUFFER_LIMITS.MIN_SIZE),e.BUFFER_LIMITS.MAX_SIZE),this.buffer.length>this.maxSize&&(this.buffer=this.buffer.slice(-this.maxSize))}filterLogs(t={}){let i=[...this.buffer];if(t.levels?.length&&(i=i.filter(e=>t.levels.includes(e.level))),t.prefixes?.length&&(i=i.filter(e=>e.prefix&&t.prefixes.includes(e.prefix))),t.excludePrefixes?.length&&(i=i.filter(e=>!e.prefix||!t.excludePrefixes.includes(e.prefix))),t.since){const r=e.parseTimeInput(t.since);i=i.filter(e=>new Date(e.timestamp)>=r)}if(t.until){const r=e.parseTimeInput(t.until);i=i.filter(e=>new Date(e.timestamp)<=r)}if(t.withStackTrace&&(i=i.filter(e=>e.location)),t.errorsOnly&&(i=i.filter(e=>"error"===e.level||"critical"===e.level)),t.search){const e=t.search.toLowerCase();i=i.filter(t=>t.message.toLowerCase().includes(e)||t.args.some(t=>String(t).toLowerCase().includes(e)))}return t.last&&(i=i.slice(-t.last)),t.first&&(i=i.slice(0,t.first)),i}exportJSON(e,t){const i=e.map(e=>({timestamp:e.timestamp,level:e.level,prefix:e.prefix,message:e.message,...t.minimal?{}:{args:e.args.slice(1),location:e.location,groupInfo:e.groupInfo}}));return t.compact?JSON.stringify(i):JSON.stringify(i,null,2)}exportCSV(t,i){const r=i.minimal?["Timestamp","Level","Prefix","Message"]:["Timestamp","Level","Prefix","Message","File","Line","Args"],n=t.map(t=>{const r=[e.formatDisplayTime(new Date(t.timestamp),"full"),t.level.toUpperCase(),t.prefix||"",`"${t.message.replace(/"/g,'""')}"`];return i.minimal||r.push(t.location?.file||"",t.location?.line?.toString()||"",`"${e.safeStringify(t.args.slice(1)).replace(/"/g,'""')}"`),r});return[r.join(","),...n.map(e=>e.join(","))].join("\n")}exportMarkdown(t,i){const r=/* @__PURE__ */new Date;let n=`# Log Export - ${e.formatDisplayTime(r,"full")}\n\n`;if(!i.minimal){const e=this.getBufferStats();n+="## Summary\n",n+=`- **Total logs**: ${t.length}\n`,n+=`- **Errors**: ${e.levelCounts.error+e.levelCounts.critical}\n`,n+=`- **Warnings**: ${e.levelCounts.warn}\n\n`}if("level"===i.groupBy){const i=t.reduce((e,t)=>{const i=t.level;e[i]||(e[i]=[]);const r=e[i];return r&&r.push(t),e},{});Object.entries(i).forEach(([t,i])=>{const r=this.getLevelEmoji(t);n+=`## ${r} ${t.toUpperCase()} (${i.length})\n\n`,i.forEach(t=>{const i=e.formatDisplayTime(new Date(t.timestamp),"time-only"),r=t.location?` (${t.location.file}:${t.location.line})`:"",o=t.prefix?` **${t.prefix}**:`:"";n+=`- \`${i}\`${o} ${t.message}${r}\n`}),n+="\n"})}else n+="## Logs\n\n",t.forEach(t=>{const i=e.formatDisplayTime(new Date(t.timestamp),"time-only"),r=this.getLevelEmoji(t.level),o=t.location?` (${t.location.file}:${t.location.line})`:"",a=t.prefix?` **${t.prefix}**:`:"";n+=`- \`${i}\` ${r}${a} ${t.message}${o}\n`});return n}exportPlain(t,i){return t.map(t=>{const r=e.formatDisplayTime(new Date(t.timestamp),i.minimal?"time-only":"short"),n=t.level.toUpperCase().padEnd(8),o=t.prefix?`[${t.prefix}] `:"",a=!i.minimal&&t.location?` (${t.location.file}:${t.location.line})`:"";return`${r} ${n} ${o}${t.message}${a}`}).join("\n")}exportHTML(t,i){const r=`Log Export - ${e.formatDisplayTime(/* @__PURE__ */new Date,"full")}`;let n=`<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>${r}</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }\n .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }\n .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }\n .timestamp { color: #666; font-size: 0.9em; }\n .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .location { color: #718096; font-size: 0.9em; }\n .debug { background: #f0f4ff; }\n .info { background: #f0f9ff; }\n .warn { background: #fffbeb; }\n .error { background: #fef2f2; }\n .critical { background: #fef2f2; border-left: 4px solid #dc2626; }\n .level.debug { background: #667eea; color: white; }\n .level.info { background: #74b9ff; color: white; }\n .level.warn { background: #fdcb6e; color: #2d3436; }\n .level.error { background: #e84393; color: white; }\n .level.critical { background: #ff3838; color: white; }\n </style>\n</head>\n<body>\n <div class="header">\n <h1>${r}</h1>\n <p>Generated by Advanced Logger v2.0.0</p>\n </div>\n <div class="logs">`;return t.forEach(t=>{const i=e.formatDisplayTime(new Date(t.timestamp),"full"),r=t.location?` <span class="location">(${e.escapeHtml(t.location.file)}:${t.location.line})</span>`:"",o=t.prefix?` <span class="prefix">${e.escapeHtml(t.prefix)}</span>`:"";n+=`\n <div class="log-entry ${t.level}">\n <span class="timestamp">${i}</span>\n <span class="level ${t.level}">${t.level.toUpperCase()}</span>\n ${o}\n <span class="message">${e.escapeHtml(t.message)}</span>\n ${r}\n </div>`}),n+="\n </div>\n</body>\n</html>",n}getLevelEmoji(e){return{debug:"🐞",info:"â„šī¸",warn:"âš ī¸",error:"❌",critical:"đŸ”Ĩ"}[e]||""}export(e,t={},i={}){const r=this.filterLogs(t);let n;switch(e){case"json":n=this.exportJSON(r,i);break;case"csv":n=this.exportCSV(r,i);break;case"markdown":n=this.exportMarkdown(r,i);break;case"plain":n=this.exportPlain(r,i);break;case"html":n=this.exportHTML(r,i);break;default:throw new Error(`Unsupported export format: ${e}`)}return{format:e,data:n,metadata:{totalLogs:this.buffer.length,filteredLogs:r.length,exportedAt:/* @__PURE__ */(new Date).toISOString(),filters:t,options:i}}}async copyToClipboard(e,t={},i={}){const r=this.export(e,t,i);try{if(navigator.clipboard&&window.isSecureContext)return await navigator.clipboard.writeText(r.data),!0;{const e=document.createElement("textarea");e.value=r.data,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.focus(),e.select();const t=document.execCommand("copy");return document.body.removeChild(e),t}}catch(n){return console.error("Failed to copy to clipboard:",n),!1}}getAllLogs(){return[...this.buffer]}},exports.RemoteLogHandler=class{endpoint;apiKey;constructor(e,t){this.endpoint=e,this.apiKey=t}async handle(e,t,i,r){try{const n={timestamp:r.timestamp,level:e,message:t,prefix:r.prefix,location:r.stackInfo,additional:i.slice(1)};await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json",...this.apiKey&&{Authorization:`Bearer ${this.apiKey}`}},body:JSON.stringify(n)})}catch(n){}}};
2
+ //# sourceMappingURL=exports-U1xLBXrY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exports-U1xLBXrY.js","sources":["../../src/handlers/ExportLogHandler.ts","../../src/handlers/RemoteLogHandler.ts"],"sourcesContent":["/**\n * @fileoverview Export and clipboard log handler for Advanced Logger\n */\n\nimport type { \n ILogHandler, \n LogLevel, \n LogMetadata, \n LogEntry, \n ExportFilters, \n ExportOptions, \n ExportResult, \n BufferStats,\n ExportFormat\n} from '../types/index.js';\nimport { parseTimeInput, formatDisplayTime, safeStringify, escapeHtml, generateLogId } from '../utils/index.js';\nimport { BUFFER_LIMITS } from '../constants.js';\n\n/**\n * Export log handler with circular buffer and multiple export formats\n */\nexport class ExportLogHandler implements ILogHandler {\n private buffer: LogEntry[] = [];\n private maxSize: number;\n private groupDepth: number = 0;\n private currentGroup?: string;\n\n constructor(maxSize: number = BUFFER_LIMITS.DEFAULT_SIZE) {\n this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);\n }\n\n /**\n * Handle incoming log and store in buffer\n */\n handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): void {\n const entry: LogEntry = {\n id: generateLogId(),\n timestamp: metadata.timestamp,\n level,\n prefix: metadata.prefix,\n message,\n args,\n location: metadata.stackInfo,\n groupInfo: this.groupDepth > 0 ? {\n depth: this.groupDepth,\n groupName: this.currentGroup\n } : undefined\n };\n\n // Add to circular buffer\n this.buffer.push(entry);\n if (this.buffer.length > this.maxSize) {\n this.buffer.shift(); // Remove oldest entry\n }\n }\n\n /**\n * Set group tracking for nested logs\n */\n setGroupInfo(depth: number, groupName?: string): void {\n this.groupDepth = depth;\n this.currentGroup = groupName;\n }\n\n /**\n * Get buffer statistics\n */\n getBufferStats(): BufferStats {\n const levelCounts = this.buffer.reduce((acc, entry) => {\n const currentCount = acc[entry.level] ? acc[entry.level] : 0;\n acc[entry.level] = currentCount + 1;\n return acc;\n }, {} as Record<LogLevel, number>);\n\n let oldestLog: Date | undefined;\n let newestLog: Date | undefined;\n \n if (this.buffer.length > 0) {\n const firstEntry = this.buffer[0];\n const lastEntry = this.buffer[this.buffer.length - 1];\n \n if (firstEntry && firstEntry.timestamp) {\n oldestLog = new Date(firstEntry.timestamp);\n }\n \n if (lastEntry && lastEntry.timestamp) {\n newestLog = new Date(lastEntry.timestamp);\n }\n }\n\n return {\n size: this.buffer.length,\n maxSize: this.maxSize,\n usage: (this.buffer.length / this.maxSize) * 100,\n oldestLog,\n newestLog,\n levelCounts: {\n debug: levelCounts.debug ? levelCounts.debug : 0,\n info: levelCounts.info ? levelCounts.info : 0,\n warn: levelCounts.warn ? levelCounts.warn : 0,\n error: levelCounts.error ? levelCounts.error : 0,\n critical: levelCounts.critical ? levelCounts.critical : 0\n }\n };\n }\n\n /**\n * Clear the buffer\n */\n clearBuffer(): void {\n this.buffer = [];\n }\n\n /**\n * Set buffer size (with limits)\n */\n setBufferSize(size: number): void {\n this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);\n \n // Trim buffer if new size is smaller\n if (this.buffer.length > this.maxSize) {\n this.buffer = this.buffer.slice(-this.maxSize);\n }\n }\n\n /**\n * Filter logs based on criteria\n */\n private filterLogs(filters: ExportFilters = {}): LogEntry[] {\n let filtered = [...this.buffer];\n\n // Filter by levels\n if (filters.levels?.length) {\n filtered = filtered.filter(entry => filters.levels!.includes(entry.level));\n }\n\n // Filter by prefixes\n if (filters.prefixes?.length) {\n filtered = filtered.filter(entry => \n entry.prefix && filters.prefixes!.includes(entry.prefix)\n );\n }\n\n // Exclude prefixes\n if (filters.excludePrefixes?.length) {\n filtered = filtered.filter(entry => \n !entry.prefix || !filters.excludePrefixes!.includes(entry.prefix)\n );\n }\n\n // Filter by time range\n if (filters.since) {\n const sinceDate = parseTimeInput(filters.since);\n filtered = filtered.filter(entry => new Date(entry.timestamp) >= sinceDate);\n }\n\n if (filters.until) {\n const untilDate = parseTimeInput(filters.until);\n filtered = filtered.filter(entry => new Date(entry.timestamp) <= untilDate);\n }\n\n // Filter by stack trace presence\n if (filters.withStackTrace) {\n filtered = filtered.filter(entry => entry.location);\n }\n\n // Filter errors only\n if (filters.errorsOnly) {\n filtered = filtered.filter(entry => entry.level === 'error' || entry.level === 'critical');\n }\n\n // Search in messages\n if (filters.search) {\n const searchTerm = filters.search.toLowerCase();\n filtered = filtered.filter(entry => \n entry.message.toLowerCase().includes(searchTerm) ||\n entry.args.some(arg => \n String(arg).toLowerCase().includes(searchTerm)\n )\n );\n }\n\n // Limit results\n if (filters.last) {\n filtered = filtered.slice(-filters.last);\n }\n\n if (filters.first) {\n filtered = filtered.slice(0, filters.first);\n }\n\n return filtered;\n }\n\n /**\n * Export logs in JSON format\n */\n private exportJSON(logs: LogEntry[], options: ExportOptions): string {\n const data = logs.map(entry => ({\n timestamp: entry.timestamp,\n level: entry.level,\n prefix: entry.prefix,\n message: entry.message,\n ...(options.minimal ? {} : {\n args: entry.args.slice(1),\n location: entry.location,\n groupInfo: entry.groupInfo\n })\n }));\n\n return options.compact \n ? JSON.stringify(data)\n : JSON.stringify(data, null, 2);\n }\n\n /**\n * Export logs in CSV format\n */\n private exportCSV(logs: LogEntry[], options: ExportOptions): string {\n const headers = options.minimal \n ? ['Timestamp', 'Level', 'Prefix', 'Message']\n : ['Timestamp', 'Level', 'Prefix', 'Message', 'File', 'Line', 'Args'];\n\n const rows = logs.map(entry => {\n const baseRow = [\n formatDisplayTime(new Date(entry.timestamp), 'full'),\n entry.level.toUpperCase(),\n entry.prefix || '',\n `\"${entry.message.replace(/\"/g, '\"\"')}\"`\n ];\n\n if (!options.minimal) {\n baseRow.push(\n entry.location?.file || '',\n entry.location?.line?.toString() || '',\n `\"${safeStringify(entry.args.slice(1)).replace(/\"/g, '\"\"')}\"`\n );\n }\n\n return baseRow;\n });\n\n return [headers.join(','), ...rows.map(row => row.join(','))].join('\\n');\n }\n\n /**\n * Export logs in Markdown format\n */\n private exportMarkdown(logs: LogEntry[], options: ExportOptions): string {\n const now = new Date();\n let content = `# Log Export - ${formatDisplayTime(now, 'full')}\\n\\n`;\n\n // Add summary if not minimal\n if (!options.minimal) {\n const summary = this.getBufferStats();\n content += `## Summary\\n`;\n content += `- **Total logs**: ${logs.length}\\n`;\n content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}\\n`;\n content += `- **Warnings**: ${summary.levelCounts.warn}\\n\\n`;\n }\n\n // Group by level if specified\n if (options.groupBy === 'level') {\n const grouped = logs.reduce((acc, entry) => {\n const level = entry.level;\n if (!acc[level]) {\n acc[level] = [];\n }\n // We just ensured the array exists above\n const levelArray = acc[level];\n if (levelArray) {\n levelArray.push(entry);\n }\n return acc;\n }, {} as Record<string, LogEntry[]>);\n\n Object.entries(grouped).forEach(([level, entries]) => {\n const emoji = this.getLevelEmoji(level as LogLevel);\n content += `## ${emoji} ${level.toUpperCase()} (${entries.length})\\n\\n`;\n \n entries.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');\n const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';\n const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';\n content += `- \\`${time}\\`${prefix} ${entry.message}${location}\\n`;\n });\n content += '\\n';\n });\n } else {\n content += '## Logs\\n\\n';\n logs.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');\n const emoji = this.getLevelEmoji(entry.level);\n const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';\n const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';\n content += `- \\`${time}\\` ${emoji}${prefix} ${entry.message}${location}\\n`;\n });\n }\n\n return content;\n }\n\n /**\n * Export logs in plain text format\n */\n private exportPlain(logs: LogEntry[], options: ExportOptions): string {\n return logs.map(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? 'time-only' : 'short');\n const level = entry.level.toUpperCase().padEnd(8);\n const prefix = entry.prefix ? `[${entry.prefix}] ` : '';\n const location = (!options.minimal && entry.location) ? ` (${entry.location.file}:${entry.location.line})` : '';\n \n return `${time} ${level} ${prefix}${entry.message}${location}`;\n }).join('\\n');\n }\n\n /**\n * Export logs in HTML format\n */\n private exportHTML(logs: LogEntry[], _options: ExportOptions): string {\n const title = `Log Export - ${formatDisplayTime(new Date(), 'full')}`;\n \n let html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${title}</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }\n .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }\n .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }\n .timestamp { color: #666; font-size: 0.9em; }\n .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }\n .location { color: #718096; font-size: 0.9em; }\n .debug { background: #f0f4ff; }\n .info { background: #f0f9ff; }\n .warn { background: #fffbeb; }\n .error { background: #fef2f2; }\n .critical { background: #fef2f2; border-left: 4px solid #dc2626; }\n .level.debug { background: #667eea; color: white; }\n .level.info { background: #74b9ff; color: white; }\n .level.warn { background: #fdcb6e; color: #2d3436; }\n .level.error { background: #e84393; color: white; }\n .level.critical { background: #ff3838; color: white; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>${title}</h1>\n <p>Generated by Advanced Logger v2.0.0</p>\n </div>\n <div class=\"logs\">`;\n\n logs.forEach(entry => {\n const time = formatDisplayTime(new Date(entry.timestamp), 'full');\n const location = entry.location ? ` <span class=\"location\">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : '';\n const prefix = entry.prefix ? ` <span class=\"prefix\">${escapeHtml(entry.prefix)}</span>` : '';\n \n html += `\n <div class=\"log-entry ${entry.level}\">\n <span class=\"timestamp\">${time}</span>\n <span class=\"level ${entry.level}\">${entry.level.toUpperCase()}</span>\n ${prefix}\n <span class=\"message\">${escapeHtml(entry.message)}</span>\n ${location}\n </div>`;\n });\n\n html += `\n </div>\n</body>\n</html>`;\n\n return html;\n }\n\n /**\n * Get emoji for log level\n */\n private getLevelEmoji(level: LogLevel): string {\n const emojis = {\n debug: '🐞',\n info: 'â„šī¸',\n warn: 'âš ī¸',\n error: '❌',\n critical: 'đŸ”Ĩ'\n };\n return emojis[level] || '';\n }\n\n /**\n * Main export function\n */\n export(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): ExportResult {\n const filteredLogs = this.filterLogs(filters);\n \n let data: string;\n switch (format) {\n case 'json':\n data = this.exportJSON(filteredLogs, options);\n break;\n case 'csv':\n data = this.exportCSV(filteredLogs, options);\n break;\n case 'markdown':\n data = this.exportMarkdown(filteredLogs, options);\n break;\n case 'plain':\n data = this.exportPlain(filteredLogs, options);\n break;\n case 'html':\n data = this.exportHTML(filteredLogs, options);\n break;\n default:\n throw new Error(`Unsupported export format: ${format}`);\n }\n\n return {\n format,\n data,\n metadata: {\n totalLogs: this.buffer.length,\n filteredLogs: filteredLogs.length,\n exportedAt: new Date().toISOString(),\n filters,\n options\n }\n };\n }\n\n /**\n * Copy to clipboard with fallback\n */\n async copyToClipboard(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): Promise<boolean> {\n const result = this.export(format, filters, options);\n \n try {\n if (navigator.clipboard && window.isSecureContext) {\n await navigator.clipboard.writeText(result.data);\n return true;\n } else {\n // Fallback for non-secure contexts\n const textArea = document.createElement('textarea');\n textArea.value = result.data;\n textArea.style.position = 'fixed';\n textArea.style.opacity = '0';\n document.body.appendChild(textArea);\n textArea.focus();\n textArea.select();\n const success = document.execCommand('copy');\n document.body.removeChild(textArea);\n return success;\n }\n } catch (error) {\n console.error('Failed to copy to clipboard:', error);\n return false;\n }\n }\n\n /**\n * Get all logs (for debugging)\n */\n getAllLogs(): LogEntry[] {\n return [...this.buffer];\n }\n}","/**\n * @fileoverview Remote log handler for Advanced Logger\n */\n\nimport type { ILogHandler, LogLevel, LogMetadata } from '../types/index.js';\n\n/**\n * Remote log handler for sending logs to external services\n */\nexport class RemoteLogHandler implements ILogHandler {\n private endpoint: string;\n private apiKey?: string;\n\n constructor(endpoint: string, apiKey?: string) {\n this.endpoint = endpoint;\n this.apiKey = apiKey;\n }\n\n async handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): Promise<void> {\n try {\n const payload = {\n timestamp: metadata.timestamp,\n level,\n message,\n prefix: metadata.prefix,\n location: metadata.stackInfo,\n additional: args.slice(1),\n };\n\n await fetch(this.endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(this.apiKey && { 'Authorization': `Bearer ${this.apiKey}` }),\n },\n body: JSON.stringify(payload),\n });\n } catch (error) {\n // Silently fail to avoid infinite logging loops\n }\n }\n}"],"names":["buffer","maxSize","groupDepth","currentGroup","constructor","BUFFER_LIMITS","DEFAULT_SIZE","this","Math","min","max","MIN_SIZE","MAX_SIZE","handle","level","message","args","metadata","entry","id","generateLogId","timestamp","prefix","location","stackInfo","groupInfo","depth","groupName","push","length","shift","setGroupInfo","getBufferStats","levelCounts","reduce","acc","currentCount","oldestLog","newestLog","firstEntry","lastEntry","Date","size","usage","debug","info","warn","error","critical","clearBuffer","setBufferSize","slice","filterLogs","filters","filtered","levels","filter","includes","prefixes","excludePrefixes","since","sinceDate","parseTimeInput","until","untilDate","withStackTrace","errorsOnly","search","searchTerm","toLowerCase","some","String","arg","last","first","exportJSON","logs","options","data","map","minimal","compact","JSON","stringify","exportCSV","headers","rows","baseRow","formatDisplayTime","toUpperCase","replace","file","line","toString","safeStringify","join","row","exportMarkdown","now","content","summary","groupBy","grouped","levelArray","Object","entries","forEach","emoji","getLevelEmoji","time","exportPlain","padEnd","exportHTML","_options","title","html","escapeHtml","format","filteredLogs","Error","totalLogs","exportedAt","toISOString","copyToClipboard","result","export","navigator","clipboard","window","isSecureContext","writeText","textArea","document","createElement","value","style","position","opacity","body","appendChild","focus","select","success","execCommand","removeChild","console","getAllLogs","endpoint","apiKey","payload","additional","fetch","method","Authorization"],"mappings":"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"}