@mks2508/better-logger 5.0.1 → 5.0.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 (310) hide show
  1. package/dist/Logger.d.ts +976 -0
  2. package/dist/Logger.d.ts.map +1 -0
  3. package/dist/ScopedLogger.d.ts +74 -0
  4. package/dist/ScopedLogger.d.ts.map +1 -0
  5. package/dist/chunks/Logger-CKqzXDh3.js +2 -0
  6. package/dist/chunks/Logger-CKqzXDh3.js.map +1 -0
  7. package/dist/chunks/Logger-D_vuKP4l.js +4511 -0
  8. package/dist/chunks/Logger-D_vuKP4l.js.map +1 -0
  9. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js +33 -0
  10. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js.map +1 -0
  11. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js +2 -0
  12. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js.map +1 -0
  13. package/dist/chunks/cli-module-B-njrTWb.js +2 -0
  14. package/dist/chunks/cli-module-B-njrTWb.js.map +1 -0
  15. package/dist/chunks/cli-module-Cx7qotPY.js +390 -0
  16. package/dist/chunks/cli-module-Cx7qotPY.js.map +1 -0
  17. package/dist/chunks/color-converter-CCSQRztd.js +2 -0
  18. package/dist/chunks/color-converter-CCSQRztd.js.map +1 -0
  19. package/dist/chunks/color-converter-_Xdmsy7E.js +462 -0
  20. package/dist/chunks/color-converter-_Xdmsy7E.js.map +1 -0
  21. package/dist/chunks/environment-C1xxvc8l.js +1127 -0
  22. package/dist/chunks/environment-C1xxvc8l.js.map +1 -0
  23. package/dist/chunks/environment-Cprkw3g9.js +4 -0
  24. package/dist/chunks/environment-Cprkw3g9.js.map +1 -0
  25. package/dist/chunks/formatting-DMJxYq9o.js +380 -0
  26. package/dist/chunks/formatting-DMJxYq9o.js.map +1 -0
  27. package/dist/chunks/formatting-DpKxCsXq.js +2 -0
  28. package/dist/chunks/formatting-DpKxCsXq.js.map +1 -0
  29. package/dist/cli/CommandProcessor.d.ts +100 -0
  30. package/dist/cli/CommandProcessor.d.ts.map +1 -0
  31. package/dist/cli/commands/ConfigCommand.d.ts +14 -0
  32. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -0
  33. package/dist/cli/commands/ExportCommand.d.ts +48 -0
  34. package/dist/cli/commands/ExportCommand.d.ts.map +1 -0
  35. package/dist/cli/commands/HistoryCommand.d.ts +47 -0
  36. package/dist/cli/commands/HistoryCommand.d.ts.map +1 -0
  37. package/dist/cli/commands/StatusCommand.d.ts +30 -0
  38. package/dist/cli/commands/StatusCommand.d.ts.map +1 -0
  39. package/dist/cli/commands/ThemeCommand.d.ts +30 -0
  40. package/dist/cli/commands/ThemeCommand.d.ts.map +1 -0
  41. package/dist/cli/help.d.ts +12 -0
  42. package/dist/cli/help.d.ts.map +1 -0
  43. package/dist/cli/index.d.ts +15 -0
  44. package/dist/cli/index.d.ts.map +1 -0
  45. package/{src/cli-module.ts → dist/cli-module.d.ts} +2 -8
  46. package/dist/cli-module.d.ts.map +1 -0
  47. package/dist/cli-primitives/box.d.ts +11 -0
  48. package/dist/cli-primitives/box.d.ts.map +1 -0
  49. package/dist/cli-primitives/cli-table.d.ts +11 -0
  50. package/dist/cli-primitives/cli-table.d.ts.map +1 -0
  51. package/dist/cli-primitives/divider.d.ts +11 -0
  52. package/dist/cli-primitives/divider.d.ts.map +1 -0
  53. package/dist/cli-primitives/header.d.ts +12 -0
  54. package/dist/cli-primitives/header.d.ts.map +1 -0
  55. package/{src/cli-primitives/index.ts → dist/cli-primitives/index.d.ts} +1 -1
  56. package/dist/cli-primitives/index.d.ts.map +1 -0
  57. package/dist/cli-primitives/server-fallback.d.ts +25 -0
  58. package/dist/cli-primitives/server-fallback.d.ts.map +1 -0
  59. package/dist/cli-primitives/spinner.d.ts +47 -0
  60. package/dist/cli-primitives/spinner.d.ts.map +1 -0
  61. package/dist/cli-primitives/step.d.ts +11 -0
  62. package/dist/cli-primitives/step.d.ts.map +1 -0
  63. package/dist/cli.cjs +2 -0
  64. package/dist/cli.cjs.map +1 -0
  65. package/dist/cli.js +12 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/constants.d.ts +235 -0
  68. package/dist/constants.d.ts.map +1 -0
  69. package/dist/core.cjs +2 -0
  70. package/dist/core.cjs.map +1 -0
  71. package/dist/core.d.ts +127 -0
  72. package/dist/core.d.ts.map +1 -0
  73. package/dist/core.js +291 -0
  74. package/dist/core.js.map +1 -0
  75. package/dist/example.d.ts +18 -0
  76. package/dist/example.d.ts.map +1 -0
  77. package/dist/exports-module.d.ts +196 -0
  78. package/dist/exports-module.d.ts.map +1 -0
  79. package/dist/exports.cjs +2 -0
  80. package/dist/exports.cjs.map +1 -0
  81. package/dist/exports.js +238 -0
  82. package/dist/exports.js.map +1 -0
  83. package/dist/handlers/AnalyticsLogHandler.d.ts +8 -0
  84. package/dist/handlers/AnalyticsLogHandler.d.ts.map +1 -0
  85. package/dist/handlers/ExportLogHandler.d.ts +100 -0
  86. package/dist/handlers/ExportLogHandler.d.ts.map +1 -0
  87. package/dist/handlers/FileLogHandler.d.ts +33 -0
  88. package/dist/handlers/FileLogHandler.d.ts.map +1 -0
  89. package/dist/handlers/RemoteLogHandler.d.ts +11 -0
  90. package/dist/handlers/RemoteLogHandler.d.ts.map +1 -0
  91. package/{src/handlers/index.ts → dist/handlers/index.d.ts} +2 -2
  92. package/dist/handlers/index.d.ts.map +1 -0
  93. package/dist/hooks/HookManager.d.ts +21 -0
  94. package/dist/hooks/HookManager.d.ts.map +1 -0
  95. package/{src/hooks/index.ts → dist/hooks/index.d.ts} +1 -0
  96. package/dist/hooks/index.d.ts.map +1 -0
  97. package/dist/index.cjs +2 -0
  98. package/dist/index.cjs.map +1 -0
  99. package/dist/index.d.ts +161 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +627 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/main.d.ts +2 -0
  104. package/dist/main.d.ts.map +1 -0
  105. package/dist/serializers/SerializerRegistry.d.ts +16 -0
  106. package/dist/serializers/SerializerRegistry.d.ts.map +1 -0
  107. package/{src/serializers/index.ts → dist/serializers/index.d.ts} +1 -0
  108. package/dist/serializers/index.d.ts.map +1 -0
  109. package/dist/styling/LogStyleBuilder.d.ts +146 -0
  110. package/dist/styling/LogStyleBuilder.d.ts.map +1 -0
  111. package/dist/styling/SemanticStyles.d.ts +178 -0
  112. package/dist/styling/SemanticStyles.d.ts.map +1 -0
  113. package/dist/styling/SmartPresets.d.ts +22 -0
  114. package/dist/styling/SmartPresets.d.ts.map +1 -0
  115. package/dist/styling/StyleBuilder.d.ts +140 -0
  116. package/dist/styling/StyleBuilder.d.ts.map +1 -0
  117. package/dist/styling/StyleCache.d.ts +42 -0
  118. package/dist/styling/StyleCache.d.ts.map +1 -0
  119. package/dist/styling/banners.d.ts +42 -0
  120. package/dist/styling/banners.d.ts.map +1 -0
  121. package/dist/styling/index.d.ts +10 -0
  122. package/dist/styling/index.d.ts.map +1 -0
  123. package/dist/styling/themes.d.ts +7 -0
  124. package/dist/styling/themes.d.ts.map +1 -0
  125. package/dist/styling-module.d.ts +178 -0
  126. package/dist/styling-module.d.ts.map +1 -0
  127. package/dist/styling.cjs +2 -0
  128. package/dist/styling.cjs.map +1 -0
  129. package/dist/styling.js +146 -0
  130. package/dist/styling.js.map +1 -0
  131. package/dist/terminal/color-converter.d.ts +73 -0
  132. package/dist/terminal/color-converter.d.ts.map +1 -0
  133. package/dist/terminal/formatter.d.ts +20 -0
  134. package/dist/terminal/formatter.d.ts.map +1 -0
  135. package/dist/terminal/terminal-renderer.d.ts +77 -0
  136. package/dist/terminal/terminal-renderer.d.ts.map +1 -0
  137. package/dist/transports/ConsoleTransport.d.ts +9 -0
  138. package/dist/transports/ConsoleTransport.d.ts.map +1 -0
  139. package/dist/transports/FileTransport.d.ts +15 -0
  140. package/dist/transports/FileTransport.d.ts.map +1 -0
  141. package/dist/transports/HttpTransport.d.ts +16 -0
  142. package/dist/transports/HttpTransport.d.ts.map +1 -0
  143. package/dist/transports/TransportManager.d.ts +14 -0
  144. package/dist/transports/TransportManager.d.ts.map +1 -0
  145. package/{src/transports/index.ts → dist/transports/index.d.ts} +1 -0
  146. package/dist/transports/index.d.ts.map +1 -0
  147. package/{src/types/core.ts → dist/types/core.d.ts} +25 -62
  148. package/dist/types/core.d.ts.map +1 -0
  149. package/{src/types/handlers.ts → dist/types/handlers.d.ts} +5 -15
  150. package/dist/types/handlers.d.ts.map +1 -0
  151. package/{src/types/hooks.ts → dist/types/hooks.d.ts} +3 -12
  152. package/dist/types/hooks.d.ts.map +1 -0
  153. package/dist/types/index.d.ts +11 -0
  154. package/dist/types/index.d.ts.map +1 -0
  155. package/{src/types/serializers.ts → dist/types/serializers.d.ts} +1 -6
  156. package/dist/types/serializers.d.ts.map +1 -0
  157. package/{src/types/transports.ts → dist/types/transports.d.ts} +2 -7
  158. package/dist/types/transports.d.ts.map +1 -0
  159. package/dist/utils/adapter.d.ts +48 -0
  160. package/dist/utils/adapter.d.ts.map +1 -0
  161. package/dist/utils/ansi-colors.d.ts +156 -0
  162. package/dist/utils/ansi-colors.d.ts.map +1 -0
  163. package/dist/utils/environment-detector.d.ts +45 -0
  164. package/dist/utils/environment-detector.d.ts.map +1 -0
  165. package/dist/utils/environment.d.ts +47 -0
  166. package/dist/utils/environment.d.ts.map +1 -0
  167. package/dist/utils/formatting.d.ts +58 -0
  168. package/dist/utils/formatting.d.ts.map +1 -0
  169. package/dist/utils/index.d.ts +8 -0
  170. package/dist/utils/index.d.ts.map +1 -0
  171. package/dist/utils/opentui-detection.d.ts +34 -0
  172. package/dist/utils/opentui-detection.d.ts.map +1 -0
  173. package/dist/utils/output.d.ts +46 -0
  174. package/dist/utils/output.d.ts.map +1 -0
  175. package/dist/utils/stackTrace.d.ts +6 -0
  176. package/dist/utils/stackTrace.d.ts.map +1 -0
  177. package/dist/utils/timestamps.d.ts +20 -0
  178. package/dist/utils/timestamps.d.ts.map +1 -0
  179. package/{src/writers/BufferWriter.ts → dist/writers/BufferWriter.d.ts} +16 -77
  180. package/dist/writers/BufferWriter.d.ts.map +1 -0
  181. package/{src/writers/index.ts → dist/writers/index.d.ts} +1 -1
  182. package/dist/writers/index.d.ts.map +1 -0
  183. package/package.json +5 -1
  184. package/.claude/settings.local.json +0 -48
  185. package/.github/workflows/ci-quality.yml +0 -357
  186. package/.github/workflows/docs-demo.yml +0 -119
  187. package/.github/workflows/releases-core.yml +0 -512
  188. package/.github/workflows/releases-full.yml +0 -582
  189. package/.github/workflows-backup/ci.yml +0 -221
  190. package/.github/workflows-backup/nightly.yml +0 -196
  191. package/.github/workflows-backup/release-optimized.yml +0 -373
  192. package/.github/workflows-backup/release.yml +0 -269
  193. package/.release-notes-0.2.0.md +0 -129
  194. package/.yamllint +0 -28
  195. package/CHANGELOG.json +0 -1120
  196. package/CHANGELOG.md +0 -209
  197. package/CLAUDE.md +0 -217
  198. package/demo.html +0 -847
  199. package/docs/API.md +0 -918
  200. package/docs/CORE.md +0 -264
  201. package/docs/DEVELOPMENT.md +0 -731
  202. package/docs/EXPORTS.md +0 -467
  203. package/docs/PACKAGES.md +0 -244
  204. package/docs/STYLING.md +0 -405
  205. package/docs/_config.yml +0 -36
  206. package/docs/index.md +0 -179
  207. package/examples/README.md +0 -208
  208. package/examples/basic-logging.js +0 -75
  209. package/examples/data-export.js +0 -234
  210. package/examples/package.json +0 -16
  211. package/examples/performance-timing.js +0 -170
  212. package/examples/simplified-api.js +0 -124
  213. package/examples/styling-themes.js +0 -207
  214. package/index.html +0 -358
  215. package/packages/core/package.json +0 -57
  216. package/packages/exports/package.json +0 -41
  217. package/packages/nodejs-opentui/README.md +0 -232
  218. package/packages/nodejs-opentui/package.json +0 -72
  219. package/packages/nodejs-opentui/src/LogRenderer.ts +0 -171
  220. package/packages/nodejs-opentui/src/OpenTUILogHandler.ts +0 -178
  221. package/packages/nodejs-opentui/src/components/LogBadge.tsx +0 -131
  222. package/packages/nodejs-opentui/src/index.ts +0 -133
  223. package/packages/nodejs-opentui/src/types.ts +0 -158
  224. package/packages/nodejs-opentui/tsconfig.json +0 -20
  225. package/packages/styling/package.json +0 -41
  226. package/playground/demo-all.ts +0 -95
  227. package/playground/demo-box.ts +0 -85
  228. package/playground/demo-levels.ts +0 -56
  229. package/playground/demo-real-world.ts +0 -98
  230. package/playground/demo-spinner.ts +0 -77
  231. package/playground/demo-steps.ts +0 -72
  232. package/playground/demo-table.ts +0 -83
  233. package/project-utils/README.md +0 -172
  234. package/project-utils/auto-release-gemini.ts +0 -1193
  235. package/project-utils/auto-release-ui.ts +0 -1329
  236. package/project-utils/commit-generator.ts +0 -1385
  237. package/project-utils/commit-ui.ts +0 -264
  238. package/project-utils/git-utils.ts +0 -199
  239. package/project-utils/github-release-manager.ts +0 -466
  240. package/project-utils/project-config.ts +0 -260
  241. package/project-utils/prompt-templates.js +0 -345
  242. package/project-utils/prompt-templates.ts +0 -422
  243. package/project-utils/version-manager.ts +0 -1078
  244. package/src/Logger.ts +0 -1858
  245. package/src/ScopedLogger.ts +0 -256
  246. package/src/cli/CommandProcessor.ts +0 -248
  247. package/src/cli/commands/ConfigCommand.ts +0 -93
  248. package/src/cli/commands/ExportCommand.ts +0 -276
  249. package/src/cli/commands/HistoryCommand.ts +0 -117
  250. package/src/cli/commands/StatusCommand.ts +0 -112
  251. package/src/cli/commands/ThemeCommand.ts +0 -88
  252. package/src/cli/help.ts +0 -127
  253. package/src/cli/index.ts +0 -71
  254. package/src/cli-primitives/box.ts +0 -86
  255. package/src/cli-primitives/cli-table.ts +0 -62
  256. package/src/cli-primitives/divider.ts +0 -17
  257. package/src/cli-primitives/header.ts +0 -18
  258. package/src/cli-primitives/server-fallback.ts +0 -54
  259. package/src/cli-primitives/spinner.ts +0 -133
  260. package/src/cli-primitives/step.ts +0 -22
  261. package/src/constants.ts +0 -313
  262. package/src/core.ts +0 -397
  263. package/src/example.ts +0 -210
  264. package/src/exports-module.ts +0 -311
  265. package/src/handlers/AnalyticsLogHandler.ts +0 -22
  266. package/src/handlers/ExportLogHandler.ts +0 -610
  267. package/src/handlers/FileLogHandler.ts +0 -169
  268. package/src/handlers/RemoteLogHandler.ts +0 -42
  269. package/src/hooks/HookManager.ts +0 -177
  270. package/src/index.ts +0 -395
  271. package/src/main.ts +0 -196
  272. package/src/serializers/SerializerRegistry.ts +0 -173
  273. package/src/style.css +0 -96
  274. package/src/styling/LogStyleBuilder.ts +0 -355
  275. package/src/styling/SemanticStyles.ts +0 -380
  276. package/src/styling/SmartPresets.ts +0 -288
  277. package/src/styling/StyleBuilder.ts +0 -319
  278. package/src/styling/StyleCache.ts +0 -131
  279. package/src/styling/banners.ts +0 -168
  280. package/src/styling/index.ts +0 -27
  281. package/src/styling/themes.ts +0 -235
  282. package/src/styling-module.ts +0 -244
  283. package/src/terminal/color-converter.ts +0 -315
  284. package/src/terminal/formatter.ts +0 -242
  285. package/src/terminal/terminal-renderer.ts +0 -342
  286. package/src/transports/ConsoleTransport.ts +0 -28
  287. package/src/transports/FileTransport.ts +0 -53
  288. package/src/transports/HttpTransport.ts +0 -56
  289. package/src/transports/TransportManager.ts +0 -130
  290. package/src/types/index.ts +0 -83
  291. package/src/typescript.svg +0 -1
  292. package/src/utils/adapter.ts +0 -291
  293. package/src/utils/ansi-colors.ts +0 -333
  294. package/src/utils/environment-detector.ts +0 -170
  295. package/src/utils/environment.ts +0 -94
  296. package/src/utils/formatting.ts +0 -332
  297. package/src/utils/index.ts +0 -33
  298. package/src/utils/opentui-detection.ts +0 -138
  299. package/src/utils/output.ts +0 -227
  300. package/src/utils/stackTrace.ts +0 -144
  301. package/src/utils/timestamps.ts +0 -80
  302. package/src/vite-env.d.ts +0 -1
  303. package/test-core-browser.html +0 -237
  304. package/test-core-node.js +0 -63
  305. package/tests/test-conflict-resolution.ts +0 -391
  306. package/tests/validate-workflows.sh +0 -131
  307. package/tests/yaml-autofix.sh +0 -146
  308. package/tsconfig.json +0 -50
  309. package/vite.config.ts +0 -256
  310. /package/{public → dist}/vite.svg +0 -0
@@ -1,610 +0,0 @@
1
- /**
2
- * @fileoverview Export and clipboard log handler for Advanced Logger
3
- */
4
-
5
- import type {
6
- ILogHandler,
7
- LogLevel,
8
- LogMetadata,
9
- LogEntry,
10
- ExportFilters,
11
- ExportOptions,
12
- ExportResult,
13
- BufferStats,
14
- ExportFormat
15
- } from '../types/index.js';
16
- import { parseTimeInput, formatDisplayTime } from '../utils/timestamps.js';
17
- import { safeStringify, escapeHtml, generateLogId } from '../utils/output.js';
18
- import { BUFFER_LIMITS } from '../constants.js';
19
-
20
- /**
21
- * Export log handler with circular buffer and multiple export formats
22
- */
23
- export class ExportLogHandler implements ILogHandler {
24
- private buffer: LogEntry[] = [];
25
- private maxSize: number;
26
- private groupDepth: number = 0;
27
- private currentGroup?: string;
28
-
29
- constructor(maxSize: number = BUFFER_LIMITS.DEFAULT_SIZE) {
30
- this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
31
- }
32
-
33
- /**
34
- * Handle incoming log and store in buffer
35
- */
36
- handle(level: LogLevel, message: string, args: any[], metadata: LogMetadata): void {
37
- const entry: LogEntry = {
38
- id: generateLogId(),
39
- timestamp: metadata.timestamp,
40
- level,
41
- prefix: metadata.prefix,
42
- message,
43
- args,
44
- location: metadata.stackInfo,
45
- groupInfo: this.groupDepth > 0 ? {
46
- depth: this.groupDepth,
47
- groupName: this.currentGroup
48
- } : undefined
49
- };
50
-
51
- // Add to circular buffer
52
- this.buffer.push(entry);
53
- if (this.buffer.length > this.maxSize) {
54
- this.buffer.shift(); // Remove oldest entry
55
- }
56
- }
57
-
58
- /**
59
- * Set group tracking for nested logs
60
- */
61
- setGroupInfo(depth: number, groupName?: string): void {
62
- this.groupDepth = depth;
63
- this.currentGroup = groupName;
64
- }
65
-
66
- /**
67
- * Get buffer statistics
68
- */
69
- getBufferStats(): BufferStats {
70
- const levelCounts = this.buffer.reduce((acc, entry) => {
71
- const currentCount = acc[entry.level] ? acc[entry.level] : 0;
72
- acc[entry.level] = currentCount + 1;
73
- return acc;
74
- }, {} as Record<LogLevel, number>);
75
-
76
- let oldestLog: Date | undefined;
77
- let newestLog: Date | undefined;
78
-
79
- if (this.buffer.length > 0) {
80
- const firstEntry = this.buffer[0];
81
- const lastEntry = this.buffer[this.buffer.length - 1];
82
-
83
- if (firstEntry && firstEntry.timestamp) {
84
- oldestLog = new Date(firstEntry.timestamp);
85
- }
86
-
87
- if (lastEntry && lastEntry.timestamp) {
88
- newestLog = new Date(lastEntry.timestamp);
89
- }
90
- }
91
-
92
- return {
93
- size: this.buffer.length,
94
- maxSize: this.maxSize,
95
- usage: (this.buffer.length / this.maxSize) * 100,
96
- oldestLog,
97
- newestLog,
98
- levelCounts: {
99
- debug: levelCounts.debug ? levelCounts.debug : 0,
100
- info: levelCounts.info ? levelCounts.info : 0,
101
- warn: levelCounts.warn ? levelCounts.warn : 0,
102
- error: levelCounts.error ? levelCounts.error : 0,
103
- critical: levelCounts.critical ? levelCounts.critical : 0
104
- }
105
- };
106
- }
107
-
108
- /**
109
- * Clear the buffer
110
- */
111
- clearBuffer(): void {
112
- this.buffer = [];
113
- }
114
-
115
- /**
116
- * Set buffer size (with limits)
117
- */
118
- setBufferSize(size: number): void {
119
- this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
120
-
121
- // Trim buffer if new size is smaller
122
- if (this.buffer.length > this.maxSize) {
123
- this.buffer = this.buffer.slice(-this.maxSize);
124
- }
125
- }
126
-
127
- /**
128
- * Filter logs based on criteria
129
- */
130
- private filterLogs(filters: ExportFilters = {}): LogEntry[] {
131
- let filtered = [...this.buffer];
132
-
133
- // Filter by levels
134
- if (filters.levels?.length) {
135
- filtered = filtered.filter(entry => filters.levels!.includes(entry.level));
136
- }
137
-
138
- // Filter by prefixes
139
- if (filters.prefixes?.length) {
140
- filtered = filtered.filter(entry =>
141
- entry.prefix && filters.prefixes!.includes(entry.prefix)
142
- );
143
- }
144
-
145
- // Exclude prefixes
146
- if (filters.excludePrefixes?.length) {
147
- filtered = filtered.filter(entry =>
148
- !entry.prefix || !filters.excludePrefixes!.includes(entry.prefix)
149
- );
150
- }
151
-
152
- // Filter by time range
153
- if (filters.since) {
154
- const sinceDate = parseTimeInput(filters.since);
155
- filtered = filtered.filter(entry => new Date(entry.timestamp) >= sinceDate);
156
- }
157
-
158
- if (filters.until) {
159
- const untilDate = parseTimeInput(filters.until);
160
- filtered = filtered.filter(entry => new Date(entry.timestamp) <= untilDate);
161
- }
162
-
163
- // Filter by stack trace presence
164
- if (filters.withStackTrace) {
165
- filtered = filtered.filter(entry => entry.location);
166
- }
167
-
168
- // Filter errors only
169
- if (filters.errorsOnly) {
170
- filtered = filtered.filter(entry => entry.level === 'error' || entry.level === 'critical');
171
- }
172
-
173
- // Search in messages
174
- if (filters.search) {
175
- const searchTerm = filters.search.toLowerCase();
176
- filtered = filtered.filter(entry =>
177
- entry.message.toLowerCase().includes(searchTerm) ||
178
- entry.args.some(arg =>
179
- String(arg).toLowerCase().includes(searchTerm)
180
- )
181
- );
182
- }
183
-
184
- // Limit results
185
- if (filters.last) {
186
- filtered = filtered.slice(-filters.last);
187
- }
188
-
189
- if (filters.first) {
190
- filtered = filtered.slice(0, filters.first);
191
- }
192
-
193
- return filtered;
194
- }
195
-
196
- /**
197
- * Export logs in JSON format
198
- */
199
- private exportJSON(logs: LogEntry[], options: ExportOptions): string {
200
- const data = logs.map(entry => ({
201
- timestamp: entry.timestamp,
202
- level: entry.level,
203
- prefix: entry.prefix,
204
- message: entry.message,
205
- ...(options.minimal ? {} : {
206
- args: entry.args.slice(1),
207
- location: entry.location,
208
- groupInfo: entry.groupInfo
209
- })
210
- }));
211
-
212
- return options.compact
213
- ? JSON.stringify(data)
214
- : JSON.stringify(data, null, 2);
215
- }
216
-
217
- /**
218
- * Export logs in CSV format
219
- */
220
- private exportCSV(logs: LogEntry[], options: ExportOptions): string {
221
- const headers = options.minimal
222
- ? ['Timestamp', 'Level', 'Prefix', 'Message']
223
- : ['Timestamp', 'Level', 'Prefix', 'Message', 'File', 'Line', 'Args'];
224
-
225
- const rows = logs.map(entry => {
226
- const baseRow = [
227
- formatDisplayTime(new Date(entry.timestamp), 'full'),
228
- entry.level.toUpperCase(),
229
- entry.prefix || '',
230
- `"${entry.message.replace(/"/g, '""')}"`
231
- ];
232
-
233
- if (!options.minimal) {
234
- baseRow.push(
235
- entry.location?.file || '',
236
- entry.location?.line?.toString() || '',
237
- `"${safeStringify(entry.args.slice(1)).replace(/"/g, '""')}"`
238
- );
239
- }
240
-
241
- return baseRow;
242
- });
243
-
244
- return [headers.join(','), ...rows.map(row => row.join(','))].join('\n');
245
- }
246
-
247
- /**
248
- * Export logs in Markdown format
249
- */
250
- private exportMarkdown(logs: LogEntry[], options: ExportOptions): string {
251
- const now = new Date();
252
- let content = `# Log Export - ${formatDisplayTime(now, 'full')}\n\n`;
253
-
254
- // Add summary if not minimal
255
- if (!options.minimal) {
256
- const summary = this.getBufferStats();
257
- content += `## Summary\n`;
258
- content += `- **Total logs**: ${logs.length}\n`;
259
- content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}\n`;
260
- content += `- **Warnings**: ${summary.levelCounts.warn}\n\n`;
261
- }
262
-
263
- // Group by level if specified
264
- if (options.groupBy === 'level') {
265
- const grouped = logs.reduce((acc, entry) => {
266
- const level = entry.level;
267
- if (!acc[level]) {
268
- acc[level] = [];
269
- }
270
- // We just ensured the array exists above
271
- const levelArray = acc[level];
272
- if (levelArray) {
273
- levelArray.push(entry);
274
- }
275
- return acc;
276
- }, {} as Record<string, LogEntry[]>);
277
-
278
- Object.entries(grouped).forEach(([level, entries]) => {
279
- const emoji = this.getLevelEmoji(level as LogLevel);
280
- content += `## ${emoji} ${level.toUpperCase()} (${entries.length})\n\n`;
281
-
282
- entries.forEach(entry => {
283
- const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');
284
- const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';
285
- const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';
286
- content += `- \`${time}\`${prefix} ${entry.message}${location}\n`;
287
- });
288
- content += '\n';
289
- });
290
- } else {
291
- content += '## Logs\n\n';
292
- logs.forEach(entry => {
293
- const time = formatDisplayTime(new Date(entry.timestamp), 'time-only');
294
- const emoji = this.getLevelEmoji(entry.level);
295
- const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : '';
296
- const prefix = entry.prefix ? ` **${entry.prefix}**:` : '';
297
- content += `- \`${time}\` ${emoji}${prefix} ${entry.message}${location}\n`;
298
- });
299
- }
300
-
301
- return content;
302
- }
303
-
304
- /**
305
- * Export logs in plain text format
306
- */
307
- private exportPlain(logs: LogEntry[], options: ExportOptions): string {
308
- return logs.map(entry => {
309
- const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? 'time-only' : 'short');
310
- const level = entry.level.toUpperCase().padEnd(8);
311
- const prefix = entry.prefix ? `[${entry.prefix}] ` : '';
312
- const location = (!options.minimal && entry.location) ? ` (${entry.location.file}:${entry.location.line})` : '';
313
-
314
- return `${time} ${level} ${prefix}${entry.message}${location}`;
315
- }).join('\n');
316
- }
317
-
318
- /**
319
- * Export logs in HTML format
320
- */
321
- private exportHTML(logs: LogEntry[], _options: ExportOptions): string {
322
- const title = `Log Export - ${formatDisplayTime(new Date(), 'full')}`;
323
-
324
- let html = `<!DOCTYPE html>
325
- <html lang="en">
326
- <head>
327
- <meta charset="UTF-8">
328
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
329
- <title>${title}</title>
330
- <style>
331
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }
332
- .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }
333
- .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }
334
- .timestamp { color: #666; font-size: 0.9em; }
335
- .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
336
- .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
337
- .location { color: #718096; font-size: 0.9em; }
338
- .debug { background: #f0f4ff; }
339
- .info { background: #f0f9ff; }
340
- .warn { background: #fffbeb; }
341
- .error { background: #fef2f2; }
342
- .critical { background: #fef2f2; border-left: 4px solid #dc2626; }
343
- .level.debug { background: #667eea; color: white; }
344
- .level.info { background: #74b9ff; color: white; }
345
- .level.warn { background: #fdcb6e; color: #2d3436; }
346
- .level.error { background: #e84393; color: white; }
347
- .level.critical { background: #ff3838; color: white; }
348
- </style>
349
- </head>
350
- <body>
351
- <div class="header">
352
- <h1>${title}</h1>
353
- <p>Generated by Advanced Logger v2.0.0</p>
354
- </div>
355
- <div class="logs">`;
356
-
357
- logs.forEach(entry => {
358
- const time = formatDisplayTime(new Date(entry.timestamp), 'full');
359
- const location = entry.location ? ` <span class="location">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : '';
360
- const prefix = entry.prefix ? ` <span class="prefix">${escapeHtml(entry.prefix)}</span>` : '';
361
-
362
- html += `
363
- <div class="log-entry ${entry.level}">
364
- <span class="timestamp">${time}</span>
365
- <span class="level ${entry.level}">${entry.level.toUpperCase()}</span>
366
- ${prefix}
367
- <span class="message">${escapeHtml(entry.message)}</span>
368
- ${location}
369
- </div>`;
370
- });
371
-
372
- html += `
373
- </div>
374
- </body>
375
- </html>`;
376
-
377
- return html;
378
- }
379
-
380
- /**
381
- * Get emoji for log level
382
- */
383
- private getLevelEmoji(level: LogLevel): string {
384
- const emojis = {
385
- debug: '🐞',
386
- info: 'ℹ️',
387
- warn: '⚠️',
388
- error: '❌',
389
- critical: '🔥'
390
- };
391
- return emojis[level] || '';
392
- }
393
-
394
- /**
395
- * Main export function
396
- */
397
- export(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): ExportResult {
398
- const filteredLogs = this.filterLogs(filters);
399
-
400
- let data: string;
401
- switch (format) {
402
- case 'json':
403
- data = this.exportJSON(filteredLogs, options);
404
- break;
405
- case 'csv':
406
- data = this.exportCSV(filteredLogs, options);
407
- break;
408
- case 'markdown':
409
- data = this.exportMarkdown(filteredLogs, options);
410
- break;
411
- case 'plain':
412
- data = this.exportPlain(filteredLogs, options);
413
- break;
414
- case 'html':
415
- data = this.exportHTML(filteredLogs, options);
416
- break;
417
- default:
418
- throw new Error(`Unsupported export format: ${format}`);
419
- }
420
-
421
- return {
422
- format,
423
- data,
424
- metadata: {
425
- totalLogs: this.buffer.length,
426
- filteredLogs: filteredLogs.length,
427
- exportedAt: new Date().toISOString(),
428
- filters,
429
- options
430
- }
431
- };
432
- }
433
-
434
- /**
435
- * Copy to clipboard with fallback
436
- */
437
- async copyToClipboard(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): Promise<boolean> {
438
- const result = this.export(format, filters, options);
439
-
440
- try {
441
- if (navigator.clipboard && window.isSecureContext) {
442
- await navigator.clipboard.writeText(result.data);
443
- return true;
444
- } else {
445
- // Fallback for non-secure contexts
446
- const textArea = document.createElement('textarea');
447
- textArea.value = result.data;
448
- textArea.style.position = 'fixed';
449
- textArea.style.opacity = '0';
450
- document.body.appendChild(textArea);
451
- textArea.focus();
452
- textArea.select();
453
- const success = document.execCommand('copy');
454
- document.body.removeChild(textArea);
455
- return success;
456
- }
457
- } catch (error) {
458
- console.error('Failed to copy to clipboard:', error);
459
- return false;
460
- }
461
- }
462
-
463
- /**
464
- * Get all logs (for debugging)
465
- */
466
- getAllLogs(): LogEntry[] {
467
- return [...this.buffer];
468
- }
469
-
470
- /**
471
- * Save export to file with download prompt
472
- */
473
- async saveToFile(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): Promise<boolean> {
474
- try {
475
- const result = this.export(format, filters, options);
476
- const blob = new Blob([result.data], {
477
- type: this.getMimeType(format)
478
- });
479
-
480
- const url = URL.createObjectURL(blob);
481
- const a = document.createElement('a');
482
- const filename = this.generateFilename(format, filters);
483
-
484
- a.href = url;
485
- a.download = filename;
486
- a.style.display = 'none';
487
- document.body.appendChild(a);
488
- a.click();
489
- document.body.removeChild(a);
490
- URL.revokeObjectURL(url);
491
-
492
- return true;
493
- } catch (error) {
494
- console.error('Failed to save file:', error);
495
- return false;
496
- }
497
- }
498
-
499
- /**
500
- * Get MIME type for format
501
- */
502
- private getMimeType(format: ExportFormat): string {
503
- const mimeTypes = {
504
- json: 'application/json',
505
- csv: 'text/csv',
506
- markdown: 'text/markdown',
507
- plain: 'text/plain',
508
- html: 'text/html'
509
- };
510
- return mimeTypes[format] || 'text/plain';
511
- }
512
-
513
- /**
514
- * Generate filename with timestamp
515
- */
516
- private generateFilename(format: ExportFormat, filters: ExportFilters): string {
517
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
518
- const prefix = filters.prefixes?.length === 1 ? `_${filters.prefixes[0]}` : '';
519
- const extension = format === 'markdown' ? 'md' : format;
520
- return `logs${prefix}_${timestamp}.${extension}`;
521
- }
522
-
523
- /**
524
- * Stream logs to external endpoint
525
- */
526
- async streamToEndpoint(endpoint: string, filters: ExportFilters = {}, options: {
527
- apiKey?: string;
528
- batchSize?: number;
529
- format?: ExportFormat
530
- } = {}): Promise<boolean> {
531
- try {
532
- const logs = this.filterLogs(filters);
533
- const batchSize = options.batchSize || 100;
534
- const format = options.format || 'json';
535
-
536
- // Send in batches
537
- for (let i = 0; i < logs.length; i += batchSize) {
538
- const batch = logs.slice(i, i + batchSize);
539
- const result = this.export(format, {}, { compact: true });
540
-
541
- const headers: Record<string, string> = {
542
- 'Content-Type': 'application/json'
543
- };
544
-
545
- if (options.apiKey) {
546
- headers['Authorization'] = `Bearer ${options.apiKey}`;
547
- }
548
-
549
- const response = await fetch(endpoint, {
550
- method: 'POST',
551
- headers,
552
- body: JSON.stringify({
553
- logs: batch,
554
- metadata: {
555
- batchIndex: Math.floor(i / batchSize),
556
- totalBatches: Math.ceil(logs.length / batchSize),
557
- timestamp: new Date().toISOString()
558
- }
559
- })
560
- });
561
-
562
- if (!response.ok) {
563
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
564
- }
565
- }
566
-
567
- return true;
568
- } catch (error) {
569
- console.error('Failed to stream logs:', error);
570
- return false;
571
- }
572
- }
573
-
574
- /**
575
- * Create export with metadata enrichment
576
- */
577
- exportWithMetadata(format: ExportFormat, filters: ExportFilters = {}, options: ExportOptions = {}): ExportResult {
578
- const baseResult = this.export(format, filters, options);
579
- const bufferStats = this.getBufferStats();
580
-
581
- return {
582
- ...baseResult,
583
- metadata: {
584
- ...baseResult.metadata,
585
- bufferStats: bufferStats,
586
- performance: {
587
- memoryUsage: this.estimateMemoryUsage(),
588
- processingTime: Date.now()
589
- },
590
- system: {
591
- userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'Node.js',
592
- timestamp: new Date().toISOString(),
593
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
594
- }
595
- } as any
596
- };
597
- }
598
-
599
- /**
600
- * Estimate memory usage of buffer
601
- */
602
- private estimateMemoryUsage(): number {
603
- const sampleEntry = this.buffer[0];
604
- if (!sampleEntry) return 0;
605
-
606
- // Rough estimation: JSON.stringify size * buffer length
607
- const sampleSize = JSON.stringify(sampleEntry).length;
608
- return sampleSize * this.buffer.length;
609
- }
610
- }