@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
@@ -0,0 +1,4511 @@
1
+ import { h as getAdaptiveColor, A as ADAPTIVE_COLORS, b as StyleBuilder, j as BUFFER_LIMITS, k as generateLogId, l as parseTimeInput, m as formatDisplayTime, n as safeStringify, o as escapeHtml, q as EXPORT_FORMATS, D as DEFAULT_CONFIG$1, r as setupThemeChangeListener, p as parseStackTrace, f as formatTimestamp, c as createStyledOutput, S as StylePresets, C as CLI_LEVEL_MAP } from "./environment-C1xxvc8l.js";
2
+ import { i as getEnvironment, k as getColorCapability, j as isRunningInTerminal } from "./color-converter-_Xdmsy7E.js";
3
+ import { c as formatBadge, k as renderStep, l as renderDivider, m as renderBox, n as renderTable, N as NoopSpinner, S as SpinnerManager, o as ServerFallback, q as renderHeader } from "./cli-module-Cx7qotPY.js";
4
+ const DEFAULT_CONFIG = {
5
+ maxDepth: 5,
6
+ circular: "placeholder",
7
+ preserveUndefined: false
8
+ };
9
+ class SerializerRegistry {
10
+ serializers = /* @__PURE__ */ new Map();
11
+ config;
12
+ constructor(config = {}) {
13
+ this.config = { ...DEFAULT_CONFIG, ...config };
14
+ this.registerDefaults();
15
+ }
16
+ registerDefaults() {
17
+ this.add(Error, (err) => ({
18
+ name: err.name,
19
+ message: err.message,
20
+ stack: err.stack?.split("\n").slice(0, 10),
21
+ ...err.cause ? { cause: this.serialize(err.cause) } : {}
22
+ }), 100);
23
+ this.add(Date, (date) => ({
24
+ iso: date.toISOString(),
25
+ timestamp: date.getTime()
26
+ }), 90);
27
+ this.add(RegExp, (regex) => ({
28
+ pattern: regex.source,
29
+ flags: regex.flags
30
+ }), 90);
31
+ this.add(Map, (map, ctx) => {
32
+ const obj = {};
33
+ map.forEach((value, key) => {
34
+ const keyStr = typeof key === "object" ? JSON.stringify(key) : String(key);
35
+ obj[keyStr] = this.serializeInternal(value, {
36
+ ...ctx,
37
+ depth: ctx.depth + 1,
38
+ path: [...ctx.path, keyStr]
39
+ });
40
+ });
41
+ return { __type: "Map", entries: obj };
42
+ }, 80);
43
+ this.add(Set, (set, ctx) => ({
44
+ __type: "Set",
45
+ values: Array.from(set).map(
46
+ (v, i) => this.serializeInternal(v, {
47
+ ...ctx,
48
+ depth: ctx.depth + 1,
49
+ path: [...ctx.path, `[${i}]`]
50
+ })
51
+ )
52
+ }), 80);
53
+ if (typeof Buffer !== "undefined") {
54
+ this.add(Buffer, (buf) => ({
55
+ __type: "Buffer",
56
+ length: buf.length,
57
+ preview: buf.slice(0, 50).toString("hex")
58
+ }), 70);
59
+ }
60
+ }
61
+ add(type, serializer, priority = 50) {
62
+ this.serializers.set(type, { type, serializer, priority });
63
+ }
64
+ remove(type) {
65
+ return this.serializers.delete(type);
66
+ }
67
+ has(type) {
68
+ return this.serializers.has(type);
69
+ }
70
+ getAll() {
71
+ return Array.from(this.serializers.values()).sort((a, b) => (b.priority ?? 50) - (a.priority ?? 50));
72
+ }
73
+ findSerializer(value) {
74
+ const sorted = this.getAll();
75
+ for (const entry of sorted) {
76
+ if (value instanceof entry.type) {
77
+ return entry;
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+ serializeInternal(value, context) {
83
+ if (value === null) return null;
84
+ if (value === void 0) return this.config.preserveUndefined ? void 0 : "[undefined]";
85
+ if (typeof value === "function") return `[Function: ${value.name || "anonymous"}]`;
86
+ if (typeof value !== "object") return value;
87
+ if (context.depth >= this.config.maxDepth) {
88
+ return "[Max Depth]";
89
+ }
90
+ if (context.seen.has(value)) {
91
+ switch (this.config.circular) {
92
+ case "error":
93
+ throw new Error(`Circular reference at ${context.path.join(".")}`);
94
+ case "skip":
95
+ return void 0;
96
+ case "placeholder":
97
+ default:
98
+ return "[Circular]";
99
+ }
100
+ }
101
+ context.seen.add(value);
102
+ const serializer = this.findSerializer(value);
103
+ if (serializer) {
104
+ return serializer.serializer(value, context);
105
+ }
106
+ if (Array.isArray(value)) {
107
+ return value.map(
108
+ (item, i) => this.serializeInternal(item, {
109
+ ...context,
110
+ depth: context.depth + 1,
111
+ path: [...context.path, `[${i}]`]
112
+ })
113
+ );
114
+ }
115
+ const result = {};
116
+ for (const [key, val] of Object.entries(value)) {
117
+ result[key] = this.serializeInternal(val, {
118
+ ...context,
119
+ depth: context.depth + 1,
120
+ path: [...context.path, key]
121
+ });
122
+ }
123
+ return result;
124
+ }
125
+ serialize(value, config) {
126
+ const mergedConfig = { ...this.config, ...config };
127
+ return this.serializeInternal(value, {
128
+ depth: 0,
129
+ maxDepth: mergedConfig.maxDepth,
130
+ path: [],
131
+ seen: /* @__PURE__ */ new WeakSet()
132
+ });
133
+ }
134
+ }
135
+ function generateId() {
136
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
137
+ }
138
+ class HookManager {
139
+ hooks = /* @__PURE__ */ new Map();
140
+ middlewares = [];
141
+ constructor() {
142
+ this.hooks.set("beforeLog", []);
143
+ this.hooks.set("afterLog", []);
144
+ this.hooks.set("onError", []);
145
+ }
146
+ on(event, callback, priority = 50) {
147
+ const registration = {
148
+ id: generateId(),
149
+ event,
150
+ callback,
151
+ priority,
152
+ once: false
153
+ };
154
+ const hooks = this.hooks.get(event);
155
+ hooks.push(registration);
156
+ hooks.sort((a, b) => b.priority - a.priority);
157
+ return () => this.removeHook(event, registration.id);
158
+ }
159
+ once(event, callback, priority = 50) {
160
+ const registration = {
161
+ id: generateId(),
162
+ event,
163
+ callback,
164
+ priority,
165
+ once: true
166
+ };
167
+ const hooks = this.hooks.get(event);
168
+ hooks.push(registration);
169
+ hooks.sort((a, b) => b.priority - a.priority);
170
+ return () => this.removeHook(event, registration.id);
171
+ }
172
+ off(event, callback) {
173
+ const hooks = this.hooks.get(event);
174
+ if (!hooks) return false;
175
+ const index = hooks.findIndex((h) => h.callback === callback);
176
+ if (index >= 0) {
177
+ hooks.splice(index, 1);
178
+ return true;
179
+ }
180
+ return false;
181
+ }
182
+ removeHook(event, id) {
183
+ const hooks = this.hooks.get(event);
184
+ if (hooks) {
185
+ const index = hooks.findIndex((h) => h.id === id);
186
+ if (index >= 0) {
187
+ hooks.splice(index, 1);
188
+ }
189
+ }
190
+ }
191
+ use(middleware, priority = 50) {
192
+ const registration = {
193
+ id: generateId(),
194
+ fn: middleware,
195
+ priority
196
+ };
197
+ this.middlewares.push(registration);
198
+ this.middlewares.sort((a, b) => b.priority - a.priority);
199
+ return () => {
200
+ const index = this.middlewares.findIndex((m) => m.id === registration.id);
201
+ if (index >= 0) {
202
+ this.middlewares.splice(index, 1);
203
+ }
204
+ };
205
+ }
206
+ async emit(event, entry) {
207
+ const hooks = this.hooks.get(event) || [];
208
+ let currentEntry = { ...entry };
209
+ const toRemove = [];
210
+ for (const hook of hooks) {
211
+ try {
212
+ const result = await hook.callback(currentEntry);
213
+ if (result) {
214
+ currentEntry = { ...currentEntry, ...result };
215
+ }
216
+ if (hook.once) {
217
+ toRemove.push(hook.id);
218
+ }
219
+ } catch (error) {
220
+ if (event !== "onError") {
221
+ await this.emit("onError", {
222
+ ...currentEntry,
223
+ error,
224
+ hookEvent: event
225
+ });
226
+ }
227
+ }
228
+ }
229
+ toRemove.forEach((id) => this.removeHook(event, id));
230
+ return currentEntry;
231
+ }
232
+ async process(entry) {
233
+ let currentEntry = { ...entry };
234
+ currentEntry = await this.emit("beforeLog", currentEntry);
235
+ if (this.middlewares.length > 0) {
236
+ let index = 0;
237
+ const executeNext = async () => {
238
+ if (index < this.middlewares.length) {
239
+ const middleware = this.middlewares[index++];
240
+ if (middleware) {
241
+ await middleware.fn(currentEntry, executeNext);
242
+ }
243
+ }
244
+ };
245
+ await executeNext();
246
+ }
247
+ return currentEntry;
248
+ }
249
+ async afterProcess(entry) {
250
+ await this.emit("afterLog", entry);
251
+ }
252
+ clear() {
253
+ this.hooks.forEach((hooks) => hooks.length = 0);
254
+ this.middlewares.length = 0;
255
+ }
256
+ getStats() {
257
+ return {
258
+ hooks: {
259
+ beforeLog: this.hooks.get("beforeLog")?.length || 0,
260
+ afterLog: this.hooks.get("afterLog")?.length || 0,
261
+ onError: this.hooks.get("onError")?.length || 0
262
+ },
263
+ middlewares: this.middlewares.length
264
+ };
265
+ }
266
+ }
267
+ const LOG_LEVELS = {
268
+ debug: 0,
269
+ info: 1,
270
+ warn: 2,
271
+ error: 3,
272
+ critical: 4
273
+ };
274
+ function generateTransportId() {
275
+ return `transport-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
276
+ }
277
+ class TransportManager {
278
+ transports = /* @__PURE__ */ new Map();
279
+ defaultLevel = "info";
280
+ constructor(defaultLevel) {
281
+ if (defaultLevel) {
282
+ this.defaultLevel = defaultLevel;
283
+ }
284
+ }
285
+ add(target) {
286
+ const id = generateTransportId();
287
+ const level = target.level || this.defaultLevel;
288
+ let transport;
289
+ if (typeof target.target === "string") {
290
+ throw new Error(`String transport targets not supported. Use inline transport object.`);
291
+ } else {
292
+ transport = target.target;
293
+ }
294
+ const entry = {
295
+ id,
296
+ transport,
297
+ options: target.options || {},
298
+ level,
299
+ levelValue: LOG_LEVELS[level]
300
+ };
301
+ this.transports.set(id, entry);
302
+ return id;
303
+ }
304
+ remove(id) {
305
+ const entry = this.transports.get(id);
306
+ if (entry) {
307
+ entry.transport.close?.();
308
+ return this.transports.delete(id);
309
+ }
310
+ return false;
311
+ }
312
+ async write(record) {
313
+ const promises = [];
314
+ for (const entry of this.transports.values()) {
315
+ if (record.levelValue < entry.levelValue) {
316
+ continue;
317
+ }
318
+ let transformedRecord = record;
319
+ if (entry.options.transform) {
320
+ const result2 = entry.options.transform(record);
321
+ if (result2 === null) continue;
322
+ transformedRecord = result2;
323
+ }
324
+ const result = entry.transport.write(transformedRecord);
325
+ if (result instanceof Promise) {
326
+ promises.push(result);
327
+ }
328
+ }
329
+ await Promise.all(promises);
330
+ }
331
+ async flush() {
332
+ const promises = [];
333
+ for (const entry of this.transports.values()) {
334
+ if (entry.transport.flush) {
335
+ const result = entry.transport.flush();
336
+ if (result instanceof Promise) {
337
+ promises.push(result);
338
+ }
339
+ }
340
+ }
341
+ await Promise.all(promises);
342
+ }
343
+ async close() {
344
+ await this.flush();
345
+ const promises = [];
346
+ for (const entry of this.transports.values()) {
347
+ if (entry.transport.close) {
348
+ const result = entry.transport.close();
349
+ if (result instanceof Promise) {
350
+ promises.push(result);
351
+ }
352
+ }
353
+ }
354
+ await Promise.all(promises);
355
+ this.transports.clear();
356
+ }
357
+ get count() {
358
+ return this.transports.size;
359
+ }
360
+ list() {
361
+ return Array.from(this.transports.keys());
362
+ }
363
+ }
364
+ const THEME_PRESETS = {
365
+ default: {
366
+ debug: {
367
+ emoji: "🐞",
368
+ label: "DEBUG",
369
+ background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
370
+ color: "#ffffff",
371
+ border: "1px solid #667eea",
372
+ shadow: "0 2px 4px rgba(102, 126, 234, 0.3)"
373
+ },
374
+ info: {
375
+ emoji: "ℹ️",
376
+ label: "INFO",
377
+ background: "linear-gradient(135deg, #74b9ff 0%, #0984e3 100%)",
378
+ color: "#ffffff",
379
+ border: "1px solid #74b9ff",
380
+ shadow: "0 2px 4px rgba(116, 185, 255, 0.3)"
381
+ },
382
+ warn: {
383
+ emoji: "⚠️",
384
+ label: "WARN",
385
+ background: "linear-gradient(135deg, #fdcb6e 0%, #e17055 100%)",
386
+ color: "#2d3436",
387
+ border: "1px solid #fdcb6e",
388
+ shadow: "0 2px 4px rgba(253, 203, 110, 0.3)"
389
+ },
390
+ error: {
391
+ emoji: "❌",
392
+ label: "ERROR",
393
+ background: "linear-gradient(135deg, #e84393 0%, #d63031 100%)",
394
+ color: "#ffffff",
395
+ border: "1px solid #e84393",
396
+ shadow: "0 2px 4px rgba(232, 67, 147, 0.3)"
397
+ },
398
+ success: {
399
+ emoji: "✅",
400
+ label: "SUCCESS",
401
+ background: "linear-gradient(135deg, #00b894 0%, #00a085 100%)",
402
+ color: "#ffffff",
403
+ border: "1px solid #00b894",
404
+ shadow: "0 2px 4px rgba(0, 184, 148, 0.3)"
405
+ },
406
+ critical: {
407
+ emoji: "🔥",
408
+ label: "CRITICAL",
409
+ background: "linear-gradient(135deg, #ff3838 0%, #ff1744 100%)",
410
+ color: "#ffffff",
411
+ border: "2px solid #ff3838",
412
+ shadow: "0 4px 8px rgba(255, 56, 56, 0.5)"
413
+ }
414
+ },
415
+ dark: {
416
+ debug: {
417
+ emoji: "🌙",
418
+ label: "DEBUG",
419
+ background: "linear-gradient(135deg, #2d3748 0%, #4a5568 100%)",
420
+ color: "#e2e8f0",
421
+ border: "1px solid #4a5568",
422
+ shadow: "0 2px 4px rgba(45, 55, 72, 0.8)"
423
+ },
424
+ info: {
425
+ emoji: "💡",
426
+ label: "INFO",
427
+ background: "linear-gradient(135deg, #1a202c 0%, #2d3748 100%)",
428
+ color: "#90cdf4",
429
+ border: "1px solid #3182ce",
430
+ shadow: "0 2px 4px rgba(26, 32, 44, 0.8)"
431
+ },
432
+ warn: {
433
+ emoji: "⚡",
434
+ label: "WARN",
435
+ background: "linear-gradient(135deg, #744210 0%, #975a16 100%)",
436
+ color: "#faf089",
437
+ border: "1px solid #d69e2e",
438
+ shadow: "0 2px 4px rgba(116, 66, 16, 0.8)"
439
+ },
440
+ error: {
441
+ emoji: "💀",
442
+ label: "ERROR",
443
+ background: "linear-gradient(135deg, #742a2a 0%, #9b2c2c 100%)",
444
+ color: "#feb2b2",
445
+ border: "1px solid #e53e3e",
446
+ shadow: "0 2px 4px rgba(116, 42, 42, 0.8)"
447
+ },
448
+ success: {
449
+ emoji: "🎯",
450
+ label: "SUCCESS",
451
+ background: "linear-gradient(135deg, #276749 0%, #2f855a 100%)",
452
+ color: "#9ae6b4",
453
+ border: "1px solid #38a169",
454
+ shadow: "0 2px 4px rgba(39, 103, 73, 0.8)"
455
+ },
456
+ critical: {
457
+ emoji: "💥",
458
+ label: "CRITICAL",
459
+ background: "linear-gradient(135deg, #1a1a1a 0%, #ff0000 100%)",
460
+ color: "#ffffff",
461
+ border: "2px solid #ff0000",
462
+ shadow: "0 4px 8px rgba(255, 0, 0, 0.9)"
463
+ }
464
+ },
465
+ neon: {
466
+ debug: {
467
+ emoji: "⚡",
468
+ label: "DEBUG",
469
+ background: "linear-gradient(135deg, #0f3460 0%, #e94560 100%)",
470
+ color: "#00ffff",
471
+ border: "1px solid #00ffff",
472
+ shadow: "0 0 10px rgba(0, 255, 255, 0.5)"
473
+ },
474
+ info: {
475
+ emoji: "🔮",
476
+ label: "INFO",
477
+ background: "linear-gradient(135deg, #16213e 0%, #0f3460 100%)",
478
+ color: "#00ff41",
479
+ border: "1px solid #00ff41",
480
+ shadow: "0 0 10px rgba(0, 255, 65, 0.5)"
481
+ },
482
+ warn: {
483
+ emoji: "⚠️",
484
+ label: "WARN",
485
+ background: "linear-gradient(135deg, #533a03 0%, #e94560 100%)",
486
+ color: "#ffff00",
487
+ border: "1px solid #ffff00",
488
+ shadow: "0 0 10px rgba(255, 255, 0, 0.5)"
489
+ },
490
+ error: {
491
+ emoji: "💥",
492
+ label: "ERROR",
493
+ background: "linear-gradient(135deg, #5c0a0a 0%, #ff073a 100%)",
494
+ color: "#ff073a",
495
+ border: "1px solid #ff073a",
496
+ shadow: "0 0 10px rgba(255, 7, 58, 0.8)"
497
+ },
498
+ success: {
499
+ emoji: "✨",
500
+ label: "SUCCESS",
501
+ background: "linear-gradient(135deg, #0a5c0a 0%, #39ff14 100%)",
502
+ color: "#39ff14",
503
+ border: "1px solid #39ff14",
504
+ shadow: "0 0 10px rgba(57, 255, 20, 0.8)"
505
+ },
506
+ critical: {
507
+ emoji: "🌟",
508
+ label: "CRITICAL",
509
+ background: "linear-gradient(135deg, #000000 0%, #ff0080 100%)",
510
+ color: "#ff0080",
511
+ border: "2px solid #ff0080",
512
+ shadow: "0 0 20px rgba(255, 0, 128, 1)"
513
+ }
514
+ },
515
+ minimal: {
516
+ debug: {
517
+ emoji: "",
518
+ label: "DEBUG",
519
+ background: "#f7fafc",
520
+ color: "#4a5568",
521
+ border: "1px solid #e2e8f0",
522
+ shadow: "none"
523
+ },
524
+ info: {
525
+ emoji: "",
526
+ label: "INFO",
527
+ background: "#ebf8ff",
528
+ color: "#2b6cb0",
529
+ border: "1px solid #bee3f8",
530
+ shadow: "none"
531
+ },
532
+ warn: {
533
+ emoji: "",
534
+ label: "WARN",
535
+ background: "#fffbf0",
536
+ color: "#c05621",
537
+ border: "1px solid #fed7aa",
538
+ shadow: "none"
539
+ },
540
+ error: {
541
+ emoji: "",
542
+ label: "ERROR",
543
+ background: "#fef5f5",
544
+ color: "#c53030",
545
+ border: "1px solid #fca5a5",
546
+ shadow: "none"
547
+ },
548
+ success: {
549
+ emoji: "",
550
+ label: "SUCCESS",
551
+ background: "#f0fff4",
552
+ color: "#2f855a",
553
+ border: "1px solid #9ae6b4",
554
+ shadow: "none"
555
+ },
556
+ critical: {
557
+ emoji: "",
558
+ label: "CRITICAL",
559
+ background: "#fef5f5",
560
+ color: "#e53e3e",
561
+ border: "2px solid #f56565",
562
+ shadow: "none"
563
+ }
564
+ },
565
+ // Additional theme variants can be added here
566
+ light: {
567
+ debug: {
568
+ emoji: "🔍",
569
+ label: "DEBUG",
570
+ background: "linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)",
571
+ color: "#1565c0",
572
+ border: "1px solid #90caf9",
573
+ shadow: "0 1px 3px rgba(33, 150, 243, 0.2)"
574
+ },
575
+ info: {
576
+ emoji: "ℹ️",
577
+ label: "INFO",
578
+ background: "linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%)",
579
+ color: "#7b1fa2",
580
+ border: "1px solid #ce93d8",
581
+ shadow: "0 1px 3px rgba(156, 39, 176, 0.2)"
582
+ },
583
+ warn: {
584
+ emoji: "⚠️",
585
+ label: "WARN",
586
+ background: "linear-gradient(135deg, #fff8e1 0%, #ffecb3 100%)",
587
+ color: "#f57c00",
588
+ border: "1px solid #ffcc02",
589
+ shadow: "0 1px 3px rgba(255, 152, 0, 0.2)"
590
+ },
591
+ error: {
592
+ emoji: "❌",
593
+ label: "ERROR",
594
+ background: "linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%)",
595
+ color: "#d32f2f",
596
+ border: "1px solid #f44336",
597
+ shadow: "0 1px 3px rgba(244, 67, 54, 0.2)"
598
+ },
599
+ success: {
600
+ emoji: "✅",
601
+ label: "SUCCESS",
602
+ background: "linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%)",
603
+ color: "#388e3c",
604
+ border: "1px solid #4caf50",
605
+ shadow: "0 1px 3px rgba(76, 175, 80, 0.2)"
606
+ },
607
+ critical: {
608
+ emoji: "🚨",
609
+ label: "CRITICAL",
610
+ background: "linear-gradient(135deg, #fce4ec 0%, #f8bbd9 100%)",
611
+ color: "#c2185b",
612
+ border: "2px solid #e91e63",
613
+ shadow: "0 2px 6px rgba(233, 30, 99, 0.3)"
614
+ }
615
+ },
616
+ cyberpunk: {
617
+ debug: {
618
+ emoji: "🤖",
619
+ label: "DEBUG",
620
+ background: "linear-gradient(135deg, #0d1b2a 0%, #415a77 100%)",
621
+ color: "#00d4aa",
622
+ border: "1px solid #00d4aa",
623
+ shadow: "0 0 15px rgba(0, 212, 170, 0.4)"
624
+ },
625
+ info: {
626
+ emoji: "🔗",
627
+ label: "INFO",
628
+ background: "linear-gradient(135deg, #1b263b 0%, #0d1b2a 100%)",
629
+ color: "#00b4d8",
630
+ border: "1px solid #00b4d8",
631
+ shadow: "0 0 15px rgba(0, 180, 216, 0.4)"
632
+ },
633
+ warn: {
634
+ emoji: "⚡",
635
+ label: "WARN",
636
+ background: "linear-gradient(135deg, #f72585 0%, #b5179e 100%)",
637
+ color: "#ffff3f",
638
+ border: "1px solid #ffff3f",
639
+ shadow: "0 0 15px rgba(255, 255, 63, 0.4)"
640
+ },
641
+ error: {
642
+ emoji: "💀",
643
+ label: "ERROR",
644
+ background: "linear-gradient(135deg, #7209b7 0%, #480ca8 100%)",
645
+ color: "#ff006e",
646
+ border: "1px solid #ff006e",
647
+ shadow: "0 0 15px rgba(255, 0, 110, 0.6)"
648
+ },
649
+ success: {
650
+ emoji: "⚡",
651
+ label: "SUCCESS",
652
+ background: "linear-gradient(135deg, #003566 0%, #001d3d 100%)",
653
+ color: "#00f5ff",
654
+ border: "1px solid #00f5ff",
655
+ shadow: "0 0 15px rgba(0, 245, 255, 0.4)"
656
+ },
657
+ critical: {
658
+ emoji: "💥",
659
+ label: "CRITICAL",
660
+ background: "linear-gradient(135deg, #000000 0%, #ff0040 100%)",
661
+ color: "#ff0040",
662
+ border: "2px solid #ff0040",
663
+ shadow: "0 0 25px rgba(255, 0, 64, 0.8)"
664
+ }
665
+ }
666
+ };
667
+ const BANNER_VARIANTS = {
668
+ simple: {
669
+ text: "🚀 ADVANCED LOGGER v2.0.0 - State-of-the-art Console Styling 🚀",
670
+ style: "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 20px; border-radius: 8px; font-weight: bold; font-size: 14px;"
671
+ },
672
+ ascii: {
673
+ text: `
674
+ ___ ____ _ __ ___ _ __ _____ _____ ____ __ ___ _____ _____ _____ ____
675
+ / _ \\ / __ \\| | / / / _ \\ | \\ | |/ ____| ____| _ \\ | | / _ \\ / ____| ___| _ | _ \\
676
+ / /_\\ \\ / / _\` | |/ / / /_\\ \\ | \\| | | | |__ | | | | | | / / \\ \\| | __| |_ | |_| | |_) |
677
+ | _ || | (_| | < | _ | | . \` | | | __| | | | | | | | | | | | |_ | _| | /| _ <
678
+ | | | |\\ \\__,_|_|\\_\\ | | | | | |\\ | |___| |____| |_| | | |__\\ \\_/ /| |__| | |___| |\\ \\| |_) |
679
+ \\_| |_/ \\____/ \\_| |_/ |_| \\_|\\_____|______|____/ |_____/\\___/ \\_____|_____|_| \\_|____/
680
+
681
+ Advanced Logger v2.0.0 - Console Excellence`,
682
+ style: 'font-family: "Courier New", Consolas, Monaco, monospace; color: #667eea; font-size: 11px; line-height: 1.2;'
683
+ },
684
+ unicode: {
685
+ text: `
686
+ ╔══════════════════════════════════════════════════════════════════════════╗
687
+ ║ 🚀 ADVANCED LOGGER v2.0.0 ║
688
+ ║ State-of-the-art Console Styling ║
689
+ ╚══════════════════════════════════════════════════════════════════════════╝`,
690
+ style: 'font-family: "Courier New", Consolas, Monaco, monospace; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 8px; font-size: 12px; line-height: 1.3;'
691
+ },
692
+ svg: {
693
+ text: " ",
694
+ style: `
695
+ background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 80'><defs><linearGradient id='grad' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:%23667eea'/><stop offset='100%' style='stop-color:%23764ba2'/></linearGradient></defs><rect width='100%' height='100%' fill='url(%23grad)' rx='8'/><text x='200' y='30' text-anchor='middle' fill='white' font-family='monospace' font-size='14' font-weight='bold'>🚀 ADVANCED LOGGER</text><text x='200' y='50' text-anchor='middle' fill='white' font-family='monospace' font-size='12'>State-of-the-art Console Styling</text><text x='200' y='65' text-anchor='middle' fill='white' font-family='monospace' font-size='10'>v2.0.0</text></svg>");
696
+ background-repeat: no-repeat;
697
+ background-size: 400px 80px;
698
+ padding: 40px 200px;
699
+ color: transparent;
700
+ display: inline-block;
701
+ border-radius: 8px;
702
+ `
703
+ },
704
+ animated: {
705
+ text: " 🚀 ADVANCED LOGGER v2.0.0 ",
706
+ style: `
707
+ background: linear-gradient(-45deg, #667eea, #764ba2, #667eea, #764ba2);
708
+ background-size: 400% 400%;
709
+ color: white;
710
+ padding: 15px 25px;
711
+ border-radius: 10px;
712
+ font-weight: bold;
713
+ font-size: 14px;
714
+ font-family: monospace;
715
+ animation: gradientShift 3s ease infinite;
716
+ display: inline-block;
717
+ `
718
+ }
719
+ };
720
+ const THEME_BANNERS = {
721
+ default: {
722
+ simple: "🚀 ADVANCED LOGGER v2.0.0 - State-of-the-art Console Styling 🚀",
723
+ style: "background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 20px; border-radius: 8px; font-weight: bold;"
724
+ },
725
+ dark: {
726
+ simple: "🌙 ADVANCED LOGGER v2.0.0 - Dark Mode Console Excellence 🌙",
727
+ style: "background: linear-gradient(135deg, #1a202c 0%, #2d3748 100%); color: #e2e8f0; padding: 12px 20px; border-radius: 8px; font-weight: bold; border: 1px solid #4a5568;"
728
+ },
729
+ neon: {
730
+ simple: "⚡ ADVANCED LOGGER v2.0.0 - Cyberpunk Console Experience ⚡",
731
+ style: "background: linear-gradient(135deg, #0f3460 0%, #e94560 100%); color: #00ffff; padding: 12px 20px; border-radius: 8px; font-weight: bold; text-shadow: 0 0 10px #00ffff;"
732
+ },
733
+ minimal: {
734
+ simple: "ADVANCED LOGGER v2.0.0 - Clean Console Styling",
735
+ style: "background: #f7fafc; color: #2d3748; padding: 8px 16px; border: 1px solid #e2e8f0; border-radius: 4px; font-weight: 500;"
736
+ },
737
+ light: {
738
+ simple: "☀️ ADVANCED LOGGER v2.0.0 - Bright Console Styling ☀️",
739
+ style: "background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); color: #495057; padding: 12px 20px; border-radius: 8px; font-weight: bold; border: 1px solid #dee2e6;"
740
+ },
741
+ cyberpunk: {
742
+ simple: "🤖 ADVANCED LOGGER v2.0.0 - Neural Console Interface 🤖",
743
+ style: "background: linear-gradient(135deg, #0d1b2a 0%, #415a77 100%); color: #00d4aa; padding: 12px 20px; border-radius: 8px; font-weight: bold; text-shadow: 0 0 10px #00d4aa; border: 1px solid #00d4aa;"
744
+ }
745
+ };
746
+ function detectBannerCapabilities() {
747
+ const userAgent = navigator.userAgent;
748
+ const isChrome = /Chrome/.test(userAgent);
749
+ const isFirefox = /Firefox/.test(userAgent);
750
+ const isSafari = /Safari/.test(userAgent) && !/Chrome/.test(userAgent);
751
+ const supportsSVG = !!document.createElementNS && !!document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGRect;
752
+ const supportsAnimations = typeof document !== "undefined" && "animationName" in document.createElement("div").style;
753
+ if (supportsAnimations && isChrome) {
754
+ return "animated";
755
+ } else if (supportsSVG && (isChrome || isFirefox)) {
756
+ return "svg";
757
+ } else if (isChrome || isFirefox) {
758
+ return "unicode";
759
+ } else if (isSafari) {
760
+ return "ascii";
761
+ }
762
+ return "simple";
763
+ }
764
+ function displayInitBanner(bannerType) {
765
+ const selectedType = bannerType || detectBannerCapabilities();
766
+ const banner = BANNER_VARIANTS[selectedType];
767
+ if (selectedType === "animated") {
768
+ const style = document.createElement("style");
769
+ style.textContent = `
770
+ @keyframes gradientShift {
771
+ 0% { background-position: 0% 50%; }
772
+ 50% { background-position: 100% 50%; }
773
+ 100% { background-position: 0% 50%; }
774
+ }
775
+ `;
776
+ document.head.appendChild(style);
777
+ }
778
+ console.log(`%c${banner.text}`, banner.style);
779
+ const features = [
780
+ "🎨 Advanced CSS Console Styling",
781
+ "📍 Automatic Stack Trace Parsing",
782
+ "🔧 Scoped Loggers & Prefixes",
783
+ "⚡ Performance Timers",
784
+ "🎯 Verbosity Filtering",
785
+ "🔌 Extensible Handlers",
786
+ "📱 Modern TypeScript Patterns",
787
+ "📤 Export & Clipboard Support"
788
+ ];
789
+ console.group(`%c✨ Features`, "background: #f8f9fa; color: #495057; padding: 4px 8px; border-radius: 4px; font-weight: bold;");
790
+ features.forEach((feature) => {
791
+ console.log(`%c${feature}`, "color: #6c757d; font-size: 13px;");
792
+ });
793
+ console.groupEnd();
794
+ console.log("");
795
+ }
796
+ class BaseStyler {
797
+ builder;
798
+ constructor(builder = new StyleBuilder()) {
799
+ this.builder = builder;
800
+ }
801
+ /**
802
+ * Primary brand color (typically blue)
803
+ */
804
+ primary() {
805
+ return this.color("#007bff");
806
+ }
807
+ /**
808
+ * Secondary color (typically gray)
809
+ */
810
+ secondary() {
811
+ return this.color("#6c757d");
812
+ }
813
+ /**
814
+ * Accent color for highlights
815
+ */
816
+ accent() {
817
+ return this.color("#17a2b8");
818
+ }
819
+ /**
820
+ * Muted/subtle color - automatically adaptive
821
+ */
822
+ muted() {
823
+ const mutedColors = { light: "#6c757d", dark: "#a0aec0" };
824
+ return this.color(getAdaptiveColor(mutedColors));
825
+ }
826
+ /**
827
+ * Success color (green)
828
+ */
829
+ success() {
830
+ return this.color("#28a745");
831
+ }
832
+ /**
833
+ * Warning color (yellow/orange)
834
+ */
835
+ warning() {
836
+ return this.color("#ffc107");
837
+ }
838
+ /**
839
+ * Danger/error color (red)
840
+ */
841
+ danger() {
842
+ return this.color("#dc3545");
843
+ }
844
+ /**
845
+ * Monospace font family
846
+ */
847
+ mono() {
848
+ this.builder.font('Monaco, Consolas, "Courier New", monospace');
849
+ return this;
850
+ }
851
+ /**
852
+ * System font family
853
+ */
854
+ system() {
855
+ this.builder.font('system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif');
856
+ return this;
857
+ }
858
+ /**
859
+ * Readable font optimized for text
860
+ */
861
+ readable() {
862
+ this.builder.font('Georgia, "Times New Roman", serif');
863
+ return this;
864
+ }
865
+ /**
866
+ * Compact spacing
867
+ */
868
+ compact() {
869
+ this.builder.padding("1px 4px").margin("0 1px");
870
+ return this;
871
+ }
872
+ /**
873
+ * Spacious layout
874
+ */
875
+ spacious() {
876
+ this.builder.padding("6px 12px").margin("2px 4px");
877
+ return this;
878
+ }
879
+ /**
880
+ * Inline display
881
+ */
882
+ inline() {
883
+ this.builder.display("inline-block");
884
+ return this;
885
+ }
886
+ /**
887
+ * Glass morphism effect
888
+ */
889
+ glassmorphic() {
890
+ this.builder.css("backdrop-filter", "blur(10px)").css("background", "rgba(255, 255, 255, 0.1)").border("1px solid rgba(255, 255, 255, 0.2)").rounded("8px");
891
+ return this;
892
+ }
893
+ /**
894
+ * Neon glow effect
895
+ */
896
+ neon() {
897
+ const neonColor = "#00ffff";
898
+ this.builder.color(neonColor).border(`1px solid ${neonColor}`).shadow(`0 0 10px ${neonColor}, 0 0 20px ${neonColor}`).css("text-shadow", `0 0 5px ${neonColor}`);
899
+ return this;
900
+ }
901
+ /**
902
+ * Gradient background
903
+ */
904
+ gradient(from = "#667eea", to = "#764ba2") {
905
+ this.builder.bg(`linear-gradient(135deg, ${from} 0%, ${to} 100%)`);
906
+ return this;
907
+ }
908
+ /**
909
+ * Bold text
910
+ */
911
+ bold() {
912
+ this.builder.bold();
913
+ return this;
914
+ }
915
+ /**
916
+ * Set color with automatic adaptation
917
+ */
918
+ color(color) {
919
+ this.builder.color(color);
920
+ return this;
921
+ }
922
+ /**
923
+ * Build the final CSS string
924
+ */
925
+ build() {
926
+ return this.builder.build();
927
+ }
928
+ }
929
+ class TimestampStyler extends BaseStyler {
930
+ /**
931
+ * Default timestamp style - subtle and informative
932
+ */
933
+ default() {
934
+ this.muted().mono();
935
+ this.builder.size("11px");
936
+ return this;
937
+ }
938
+ /**
939
+ * Hide timestamp
940
+ */
941
+ hidden() {
942
+ this.builder.display("none");
943
+ return this;
944
+ }
945
+ /**
946
+ * Minimal timestamp (just time, no date)
947
+ */
948
+ minimal() {
949
+ this.muted().mono();
950
+ this.builder.size("10px").opacity(0.7);
951
+ return this;
952
+ }
953
+ /**
954
+ * Set font size
955
+ */
956
+ size(size) {
957
+ this.builder.size(size);
958
+ return this;
959
+ }
960
+ }
961
+ class LevelStyler extends BaseStyler {
962
+ /**
963
+ * Colorful gradient badge
964
+ */
965
+ badge() {
966
+ this.builder.padding("2px 8px").rounded("4px").bold().color("#ffffff");
967
+ return this;
968
+ }
969
+ /**
970
+ * Glowing effect for dark themes
971
+ */
972
+ glowing() {
973
+ return this.neon().badge();
974
+ }
975
+ /**
976
+ * Minimal flat style
977
+ */
978
+ flat() {
979
+ this.builder.padding("1px 6px").rounded("2px").border("1px solid currentColor").css("background", "transparent");
980
+ return this;
981
+ }
982
+ /**
983
+ * Uppercase text
984
+ */
985
+ uppercase() {
986
+ this.builder.uppercase();
987
+ return this;
988
+ }
989
+ }
990
+ class PrefixStyler extends BaseStyler {
991
+ /**
992
+ * Dark theme prefix
993
+ */
994
+ dark() {
995
+ const prefixColors = { light: "#2d3748", dark: "#4a5568" };
996
+ const textColors = { light: "#e2e8f0", dark: "#f7fafc" };
997
+ this.builder.bg(getAdaptiveColor(prefixColors)).color(getAdaptiveColor(textColors)).padding("2px 6px").rounded("3px").bold().mono().size("11px");
998
+ return this;
999
+ }
1000
+ /**
1001
+ * Light theme prefix
1002
+ */
1003
+ light() {
1004
+ this.builder.bg("#f8f9fa").color("#495057").padding("2px 6px").rounded("3px").bold().mono().size("11px").border("1px solid #dee2e6");
1005
+ return this;
1006
+ }
1007
+ /**
1008
+ * Compact prefix
1009
+ */
1010
+ compact() {
1011
+ this.builder.padding("1px 4px").size("10px").rounded("2px");
1012
+ return this;
1013
+ }
1014
+ }
1015
+ class MessageStyler extends BaseStyler {
1016
+ /**
1017
+ * Readable message text - automatically adaptive
1018
+ */
1019
+ readable() {
1020
+ this.builder.color(getAdaptiveColor(ADAPTIVE_COLORS.messageText)).system().size("14px");
1021
+ return this;
1022
+ }
1023
+ /**
1024
+ * Code-style monospace text
1025
+ */
1026
+ code() {
1027
+ this.builder.mono().size("13px").color(getAdaptiveColor(ADAPTIVE_COLORS.messageText)).bg("rgba(0, 0, 0, 0.05)").padding("1px 4px").rounded("3px");
1028
+ return this;
1029
+ }
1030
+ /**
1031
+ * Large, prominent text
1032
+ */
1033
+ large() {
1034
+ this.builder.size("16px").color(getAdaptiveColor(ADAPTIVE_COLORS.messageText));
1035
+ return this;
1036
+ }
1037
+ }
1038
+ class LocationStyler extends BaseStyler {
1039
+ /**
1040
+ * Subtle location info - automatically adaptive
1041
+ */
1042
+ subtle() {
1043
+ this.builder.color(getAdaptiveColor(ADAPTIVE_COLORS.location)).mono().size("11px").opacity(0.7);
1044
+ return this;
1045
+ }
1046
+ /**
1047
+ * Hide location info
1048
+ */
1049
+ hidden() {
1050
+ this.builder.display("none");
1051
+ return this;
1052
+ }
1053
+ /**
1054
+ * Clickable style (for IDE integration)
1055
+ */
1056
+ clickable() {
1057
+ this.subtle();
1058
+ this.builder.css("text-decoration", "underline").cursor("pointer");
1059
+ return this;
1060
+ }
1061
+ }
1062
+ class LogStyleBuilder {
1063
+ logStyles = {};
1064
+ logger;
1065
+ constructor(logger) {
1066
+ this.logger = logger;
1067
+ }
1068
+ /**
1069
+ * Configure timestamp styling
1070
+ */
1071
+ timestamp() {
1072
+ return new TimestampStyleBuilderProxy(this);
1073
+ }
1074
+ /**
1075
+ * Configure level badge styling
1076
+ */
1077
+ level() {
1078
+ return new LevelStyleBuilderProxy(this);
1079
+ }
1080
+ /**
1081
+ * Configure prefix styling
1082
+ */
1083
+ prefix() {
1084
+ return new PrefixStyleBuilderProxy(this);
1085
+ }
1086
+ /**
1087
+ * Configure message text styling
1088
+ */
1089
+ message() {
1090
+ return new MessageStyleBuilderProxy(this);
1091
+ }
1092
+ /**
1093
+ * Configure location info styling
1094
+ */
1095
+ location() {
1096
+ return new LocationStyleBuilderProxy(this);
1097
+ }
1098
+ /**
1099
+ * Use a predefined preset
1100
+ */
1101
+ usePreset(presetName) {
1102
+ console.warn(`Preset '${presetName}' will be available in next implementation phase`);
1103
+ return this;
1104
+ }
1105
+ /**
1106
+ * Customize with partial configuration
1107
+ */
1108
+ customize(overrides) {
1109
+ this.logStyles = { ...this.logStyles, ...overrides };
1110
+ return this;
1111
+ }
1112
+ /**
1113
+ * Set layout spacing
1114
+ */
1115
+ spacing(type) {
1116
+ if (!this.logStyles.layout) {
1117
+ this.logStyles.layout = { spacing: type };
1118
+ } else {
1119
+ this.logStyles.layout.spacing = type;
1120
+ }
1121
+ switch (type) {
1122
+ case "compact":
1123
+ this.logStyles.layout.innerPadding = "1px";
1124
+ this.logStyles.layout.outerMargin = "0px";
1125
+ break;
1126
+ case "spacious":
1127
+ this.logStyles.layout.innerPadding = "4px";
1128
+ this.logStyles.layout.outerMargin = "2px";
1129
+ break;
1130
+ default:
1131
+ this.logStyles.layout.innerPadding = "2px";
1132
+ this.logStyles.layout.outerMargin = "1px";
1133
+ }
1134
+ return this;
1135
+ }
1136
+ /**
1137
+ * Set backdrop filter for glassmorphism effects
1138
+ */
1139
+ backdrop(filter) {
1140
+ this.logStyles.backdrop = filter;
1141
+ return this;
1142
+ }
1143
+ /**
1144
+ * Set overall transparency
1145
+ */
1146
+ transparency(value) {
1147
+ this.logStyles.transparency = Math.max(0, Math.min(1, value));
1148
+ return this;
1149
+ }
1150
+ /**
1151
+ * Apply the configured styles to the logger
1152
+ */
1153
+ apply() {
1154
+ this.logger._customLogStyles = this.logStyles;
1155
+ console.log("Applied log styles:", this.logStyles);
1156
+ }
1157
+ /**
1158
+ * Get current configuration (for debugging)
1159
+ */
1160
+ getConfig() {
1161
+ return { ...this.logStyles };
1162
+ }
1163
+ /**
1164
+ * Internal method to update part configuration
1165
+ */
1166
+ _updatePartConfig(part, styles) {
1167
+ if (part === "layout" || part === "backdrop" || part === "transparency") {
1168
+ return;
1169
+ }
1170
+ if (!this.logStyles[part]) {
1171
+ this.logStyles[part] = {};
1172
+ }
1173
+ this.logStyles[part].style = styles;
1174
+ }
1175
+ }
1176
+ class PartStyleBuilderProxy {
1177
+ parentBuilder;
1178
+ partName;
1179
+ constructor(parentBuilder, partName) {
1180
+ this.parentBuilder = parentBuilder;
1181
+ this.partName = partName;
1182
+ }
1183
+ /**
1184
+ * Return to the main builder for chaining other parts
1185
+ */
1186
+ and() {
1187
+ return this.parentBuilder;
1188
+ }
1189
+ /**
1190
+ * Apply styles and finish configuration
1191
+ */
1192
+ apply() {
1193
+ this.parentBuilder.apply();
1194
+ }
1195
+ /**
1196
+ * Helper to apply styles to the parent builder
1197
+ */
1198
+ applyStyles(styler) {
1199
+ const styles = styler.build();
1200
+ this.parentBuilder._updatePartConfig(this.partName, styles);
1201
+ return this;
1202
+ }
1203
+ }
1204
+ class TimestampStyleBuilderProxy extends PartStyleBuilderProxy {
1205
+ constructor(parentBuilder) {
1206
+ super(parentBuilder, "timestamp");
1207
+ }
1208
+ default() {
1209
+ return this.applyStyles(new TimestampStyler().default());
1210
+ }
1211
+ hidden() {
1212
+ return this.applyStyles(new TimestampStyler().hidden());
1213
+ }
1214
+ minimal() {
1215
+ return this.applyStyles(new TimestampStyler().minimal());
1216
+ }
1217
+ muted() {
1218
+ return this.applyStyles(new TimestampStyler().muted());
1219
+ }
1220
+ mono() {
1221
+ return this.applyStyles(new TimestampStyler().mono());
1222
+ }
1223
+ compact() {
1224
+ return this.applyStyles(new TimestampStyler().compact());
1225
+ }
1226
+ }
1227
+ class LevelStyleBuilderProxy extends PartStyleBuilderProxy {
1228
+ constructor(parentBuilder) {
1229
+ super(parentBuilder, "level");
1230
+ }
1231
+ badge() {
1232
+ return this.applyStyles(new LevelStyler().badge());
1233
+ }
1234
+ gradient(from, to) {
1235
+ return this.applyStyles(new LevelStyler().gradient(from, to));
1236
+ }
1237
+ glowing() {
1238
+ return this.applyStyles(new LevelStyler().glowing());
1239
+ }
1240
+ flat() {
1241
+ return this.applyStyles(new LevelStyler().flat());
1242
+ }
1243
+ bold() {
1244
+ return this.applyStyles(new LevelStyler().bold());
1245
+ }
1246
+ uppercase() {
1247
+ return this.applyStyles(new LevelStyler().uppercase());
1248
+ }
1249
+ neon() {
1250
+ return this.applyStyles(new LevelStyler().neon());
1251
+ }
1252
+ }
1253
+ class PrefixStyleBuilderProxy extends PartStyleBuilderProxy {
1254
+ constructor(parentBuilder) {
1255
+ super(parentBuilder, "prefix");
1256
+ }
1257
+ dark() {
1258
+ return this.applyStyles(new PrefixStyler().dark());
1259
+ }
1260
+ light() {
1261
+ return this.applyStyles(new PrefixStyler().light());
1262
+ }
1263
+ compact() {
1264
+ return this.applyStyles(new PrefixStyler().compact());
1265
+ }
1266
+ muted() {
1267
+ return this.applyStyles(new PrefixStyler().muted());
1268
+ }
1269
+ mono() {
1270
+ return this.applyStyles(new PrefixStyler().mono());
1271
+ }
1272
+ }
1273
+ class MessageStyleBuilderProxy extends PartStyleBuilderProxy {
1274
+ constructor(parentBuilder) {
1275
+ super(parentBuilder, "message");
1276
+ }
1277
+ readable() {
1278
+ return this.applyStyles(new MessageStyler().readable());
1279
+ }
1280
+ code() {
1281
+ return this.applyStyles(new MessageStyler().code());
1282
+ }
1283
+ large() {
1284
+ return this.applyStyles(new MessageStyler().large());
1285
+ }
1286
+ system() {
1287
+ return this.applyStyles(new MessageStyler().system());
1288
+ }
1289
+ mono() {
1290
+ return this.applyStyles(new MessageStyler().mono());
1291
+ }
1292
+ }
1293
+ class LocationStyleBuilderProxy extends PartStyleBuilderProxy {
1294
+ constructor(parentBuilder) {
1295
+ super(parentBuilder, "location");
1296
+ }
1297
+ subtle() {
1298
+ return this.applyStyles(new LocationStyler().subtle());
1299
+ }
1300
+ hidden() {
1301
+ return this.applyStyles(new LocationStyler().hidden());
1302
+ }
1303
+ clickable() {
1304
+ return this.applyStyles(new LocationStyler().clickable());
1305
+ }
1306
+ muted() {
1307
+ return this.applyStyles(new LocationStyler().muted());
1308
+ }
1309
+ mono() {
1310
+ return this.applyStyles(new LocationStyler().mono());
1311
+ }
1312
+ }
1313
+ function createLogStyleBuilder(logger) {
1314
+ return new LogStyleBuilder(logger);
1315
+ }
1316
+ const SMART_PRESETS = {
1317
+ /**
1318
+ * Default preset - works perfectly out-of-the-box
1319
+ * Clean, readable, automatically adaptive to dark/light themes
1320
+ */
1321
+ default: {
1322
+ layout: {
1323
+ spacing: "normal",
1324
+ innerPadding: "2px",
1325
+ outerMargin: "1px"
1326
+ },
1327
+ timestamp: {
1328
+ show: true,
1329
+ color: "auto",
1330
+ // Automatically adaptive
1331
+ font: "Monaco, Consolas, monospace",
1332
+ size: "11px"
1333
+ },
1334
+ level: {
1335
+ show: true,
1336
+ style: "badge",
1337
+ uppercase: false,
1338
+ padding: "2px 8px"
1339
+ },
1340
+ prefix: {
1341
+ show: true,
1342
+ style: "dark",
1343
+ // Automatically adaptive
1344
+ padding: "2px 6px"
1345
+ },
1346
+ message: {
1347
+ show: true,
1348
+ color: "auto",
1349
+ // Automatically adaptive
1350
+ font: "system-ui, -apple-system, sans-serif",
1351
+ size: "14px"
1352
+ },
1353
+ location: {
1354
+ show: true,
1355
+ color: "auto",
1356
+ // Automatically adaptive
1357
+ font: "Monaco, Consolas, monospace",
1358
+ size: "11px"
1359
+ }
1360
+ },
1361
+ /**
1362
+ * Cyberpunk preset - neon colors, glowing effects, dark theme
1363
+ */
1364
+ cyberpunk: {
1365
+ layout: {
1366
+ spacing: "compact",
1367
+ innerPadding: "1px",
1368
+ outerMargin: "0px"
1369
+ },
1370
+ timestamp: {
1371
+ show: true,
1372
+ color: "#00ffff",
1373
+ font: "Monaco, Consolas, monospace",
1374
+ size: "10px",
1375
+ style: "neon"
1376
+ },
1377
+ level: {
1378
+ show: true,
1379
+ style: "glowing",
1380
+ uppercase: true,
1381
+ padding: "2px 8px"
1382
+ },
1383
+ prefix: {
1384
+ show: true,
1385
+ color: "#ff0080",
1386
+ background: "rgba(255, 0, 128, 0.1)",
1387
+ border: "1px solid #ff0080",
1388
+ style: "neon"
1389
+ },
1390
+ message: {
1391
+ show: true,
1392
+ color: "#00ff41",
1393
+ font: "Monaco, Consolas, monospace",
1394
+ size: "13px"
1395
+ },
1396
+ location: {
1397
+ show: false
1398
+ // Hidden for cleaner look
1399
+ },
1400
+ backdrop: "blur(2px)",
1401
+ transparency: 0.9
1402
+ },
1403
+ /**
1404
+ * Glassmorphism preset - modern blur effects, transparency
1405
+ */
1406
+ glassmorphism: {
1407
+ layout: {
1408
+ spacing: "spacious",
1409
+ innerPadding: "4px",
1410
+ outerMargin: "2px"
1411
+ },
1412
+ timestamp: {
1413
+ show: true,
1414
+ color: "auto",
1415
+ font: "system-ui, sans-serif",
1416
+ size: "11px",
1417
+ style: "glassmorphic"
1418
+ },
1419
+ level: {
1420
+ show: true,
1421
+ style: "glassmorphic",
1422
+ uppercase: false,
1423
+ padding: "4px 12px"
1424
+ },
1425
+ prefix: {
1426
+ show: true,
1427
+ style: "glassmorphic",
1428
+ padding: "3px 8px"
1429
+ },
1430
+ message: {
1431
+ show: true,
1432
+ color: "auto",
1433
+ font: "system-ui, sans-serif",
1434
+ size: "14px"
1435
+ },
1436
+ location: {
1437
+ show: true,
1438
+ color: "auto",
1439
+ font: "system-ui, sans-serif",
1440
+ size: "11px",
1441
+ style: "glassmorphic"
1442
+ },
1443
+ backdrop: "blur(10px)",
1444
+ transparency: 0.8
1445
+ },
1446
+ /**
1447
+ * Minimal preset - clean, no decorations, maximum readability
1448
+ */
1449
+ minimal: {
1450
+ layout: {
1451
+ spacing: "compact",
1452
+ innerPadding: "0px",
1453
+ outerMargin: "0px"
1454
+ },
1455
+ timestamp: {
1456
+ show: false
1457
+ // Hidden for minimal look
1458
+ },
1459
+ level: {
1460
+ show: true,
1461
+ style: "flat",
1462
+ uppercase: true,
1463
+ padding: "0px 4px",
1464
+ border: "none",
1465
+ background: "transparent"
1466
+ },
1467
+ prefix: {
1468
+ show: true,
1469
+ style: "flat",
1470
+ padding: "0px 4px",
1471
+ border: "none",
1472
+ background: "transparent"
1473
+ },
1474
+ message: {
1475
+ show: true,
1476
+ color: "auto",
1477
+ font: "system-ui, sans-serif",
1478
+ size: "14px"
1479
+ },
1480
+ location: {
1481
+ show: false
1482
+ // Hidden for minimal look
1483
+ }
1484
+ },
1485
+ /**
1486
+ * Debug preset - monospace, detailed, compact for development
1487
+ */
1488
+ debug: {
1489
+ layout: {
1490
+ spacing: "compact",
1491
+ innerPadding: "1px",
1492
+ outerMargin: "0px"
1493
+ },
1494
+ timestamp: {
1495
+ show: true,
1496
+ color: "auto",
1497
+ font: "Monaco, Consolas, monospace",
1498
+ size: "10px"
1499
+ },
1500
+ level: {
1501
+ show: true,
1502
+ style: "compact",
1503
+ uppercase: true,
1504
+ padding: "1px 4px",
1505
+ font: "Monaco, Consolas, monospace",
1506
+ size: "10px"
1507
+ },
1508
+ prefix: {
1509
+ show: true,
1510
+ style: "compact",
1511
+ padding: "1px 4px",
1512
+ font: "Monaco, Consolas, monospace",
1513
+ size: "10px"
1514
+ },
1515
+ message: {
1516
+ show: true,
1517
+ color: "auto",
1518
+ font: "Monaco, Consolas, monospace",
1519
+ size: "12px"
1520
+ },
1521
+ location: {
1522
+ show: true,
1523
+ color: "auto",
1524
+ font: "Monaco, Consolas, monospace",
1525
+ size: "10px",
1526
+ style: "clickable"
1527
+ }
1528
+ },
1529
+ /**
1530
+ * Production preset - clean, essential info only
1531
+ */
1532
+ production: {
1533
+ layout: {
1534
+ spacing: "normal",
1535
+ innerPadding: "2px",
1536
+ outerMargin: "1px"
1537
+ },
1538
+ timestamp: {
1539
+ show: true,
1540
+ color: "auto",
1541
+ font: "system-ui, sans-serif",
1542
+ size: "11px"
1543
+ },
1544
+ level: {
1545
+ show: true,
1546
+ style: "badge",
1547
+ uppercase: false,
1548
+ padding: "2px 6px"
1549
+ },
1550
+ prefix: {
1551
+ show: false
1552
+ // Hidden in production
1553
+ },
1554
+ message: {
1555
+ show: true,
1556
+ color: "auto",
1557
+ font: "system-ui, sans-serif",
1558
+ size: "14px"
1559
+ },
1560
+ location: {
1561
+ show: false
1562
+ // Hidden in production
1563
+ }
1564
+ }
1565
+ };
1566
+ function getSmartPreset(name) {
1567
+ return SMART_PRESETS[name] || null;
1568
+ }
1569
+ function getAvailablePresets() {
1570
+ return Object.keys(SMART_PRESETS);
1571
+ }
1572
+ function hasPreset(name) {
1573
+ return name in SMART_PRESETS;
1574
+ }
1575
+ class ScopedLogger {
1576
+ parent;
1577
+ scopeName;
1578
+ badgeList = [];
1579
+ contextStack = [];
1580
+ _timers;
1581
+ constructor(parent, scopeName) {
1582
+ this.parent = parent;
1583
+ this.scopeName = scopeName;
1584
+ }
1585
+ get timers() {
1586
+ if (!this._timers) this._timers = /* @__PURE__ */ new Map();
1587
+ return this._timers;
1588
+ }
1589
+ getBindings() {
1590
+ return {
1591
+ scope: this.getScopePrefix(),
1592
+ badges: this.badgeList.length > 0 ? [...this.badgeList] : void 0
1593
+ };
1594
+ }
1595
+ getScopePrefix() {
1596
+ if (this.contextStack.length === 0) return this.scopeName;
1597
+ return [this.scopeName, ...this.contextStack].join(":");
1598
+ }
1599
+ badges(badges) {
1600
+ this.badgeList = [...badges];
1601
+ return this;
1602
+ }
1603
+ badge(badge) {
1604
+ if (!this.badgeList.includes(badge)) {
1605
+ this.badgeList.push(badge);
1606
+ }
1607
+ return this;
1608
+ }
1609
+ clearBadges() {
1610
+ this.badgeList = [];
1611
+ return this;
1612
+ }
1613
+ style(presetName) {
1614
+ this.parent.setTheme(presetName);
1615
+ return this;
1616
+ }
1617
+ context(contextName) {
1618
+ return new ContextLogger(this, contextName);
1619
+ }
1620
+ time(label) {
1621
+ this.timers.set(label, {
1622
+ label: `${this.scopeName}:${label}`,
1623
+ startTime: performance.now()
1624
+ });
1625
+ }
1626
+ timeEnd(label) {
1627
+ const timer = this.timers.get(label);
1628
+ if (!timer) {
1629
+ this.warn(`Timer '${label}' not found`);
1630
+ return void 0;
1631
+ }
1632
+ const elapsed = performance.now() - timer.startTime;
1633
+ this.timers.delete(label);
1634
+ this.success(`Timer: ${label} - ${elapsed.toFixed(2)}ms`);
1635
+ return elapsed;
1636
+ }
1637
+ debug(...args) {
1638
+ this.parent.logWithBindings(this.getBindings(), "debug", ...args);
1639
+ }
1640
+ info(...args) {
1641
+ this.parent.logWithBindings(this.getBindings(), "info", ...args);
1642
+ }
1643
+ warn(...args) {
1644
+ this.parent.logWithBindings(this.getBindings(), "warn", ...args);
1645
+ }
1646
+ error(...args) {
1647
+ this.parent.logWithBindings(this.getBindings(), "error", ...args);
1648
+ }
1649
+ success(...args) {
1650
+ const bindings = this.getBindings();
1651
+ this.parent.logWithBindings(bindings, "info", ...args);
1652
+ }
1653
+ critical(...args) {
1654
+ this.parent.logWithBindings(this.getBindings(), "critical", ...args);
1655
+ }
1656
+ trace(...args) {
1657
+ this.parent.logWithBindings(this.getBindings(), "debug", ...args);
1658
+ console.trace(`[${this.scopeName}]`);
1659
+ }
1660
+ // ===== CLI PRIMITIVES (v5.0 delegation) =====
1661
+ /** @see Logger.step */
1662
+ step(current, total, message) {
1663
+ this.parent.step(current, total, message);
1664
+ }
1665
+ /** @see Logger.header */
1666
+ header(title, subtitle) {
1667
+ this.parent.header(title, subtitle);
1668
+ }
1669
+ /** @see Logger.divider */
1670
+ divider() {
1671
+ this.parent.divider();
1672
+ }
1673
+ /** @see Logger.blank */
1674
+ blank() {
1675
+ this.parent.blank();
1676
+ }
1677
+ /** @see Logger.box */
1678
+ box(content, options) {
1679
+ this.parent.box(content, options);
1680
+ }
1681
+ /** @see Logger.cliTable */
1682
+ cliTable(rows, options) {
1683
+ this.parent.cliTable(rows, options);
1684
+ }
1685
+ /** @see Logger.spinner */
1686
+ spinner(message) {
1687
+ return this.parent.spinner(message);
1688
+ }
1689
+ /** @see Logger.setCLILevel */
1690
+ setCLILevel(level) {
1691
+ this.parent.setCLILevel(level);
1692
+ }
1693
+ _pushContext(context) {
1694
+ this.contextStack.push(context);
1695
+ }
1696
+ _popContext() {
1697
+ this.contextStack.pop();
1698
+ }
1699
+ }
1700
+ class APILogger extends ScopedLogger {
1701
+ constructor(parent, apiName) {
1702
+ super(parent, `API:${apiName}`);
1703
+ this.badge("API");
1704
+ }
1705
+ slow(message, duration) {
1706
+ this.badge("SLOW");
1707
+ const msg = duration ? `${message} (${duration}ms)` : message;
1708
+ this.warn(msg);
1709
+ }
1710
+ rateLimit(message) {
1711
+ this.badge("RATE_LIMIT");
1712
+ this.warn(message);
1713
+ }
1714
+ auth(message) {
1715
+ this.badge("AUTH");
1716
+ this.error(message);
1717
+ }
1718
+ deprecated(message) {
1719
+ this.badge("DEPRECATED");
1720
+ this.warn(message);
1721
+ }
1722
+ }
1723
+ class ComponentLogger extends ScopedLogger {
1724
+ constructor(parent, componentName) {
1725
+ super(parent, componentName);
1726
+ this.badge("COMPONENT");
1727
+ }
1728
+ lifecycle(event, message) {
1729
+ this.badge("LIFECYCLE");
1730
+ const msg = message ? `${event}: ${message}` : event;
1731
+ this.info(msg);
1732
+ }
1733
+ stateChange(from, to, data) {
1734
+ this.badge("STATE");
1735
+ const msg = `${from} → ${to}`;
1736
+ if (data) {
1737
+ this.info(msg, data);
1738
+ } else {
1739
+ this.info(msg);
1740
+ }
1741
+ }
1742
+ propsChange(changes) {
1743
+ this.badge("PROPS");
1744
+ this.debug("Props changed:", changes);
1745
+ }
1746
+ }
1747
+ class ContextLogger {
1748
+ parentLogger;
1749
+ contextName;
1750
+ constructor(parentLogger, contextName) {
1751
+ this.parentLogger = parentLogger;
1752
+ this.contextName = contextName;
1753
+ }
1754
+ run(fn) {
1755
+ this.parentLogger._pushContext(this.contextName);
1756
+ try {
1757
+ return fn();
1758
+ } finally {
1759
+ this.parentLogger._popContext();
1760
+ }
1761
+ }
1762
+ async runAsync(fn) {
1763
+ this.parentLogger._pushContext(this.contextName);
1764
+ try {
1765
+ return await fn();
1766
+ } finally {
1767
+ this.parentLogger._popContext();
1768
+ }
1769
+ }
1770
+ start() {
1771
+ this.parentLogger._pushContext(this.contextName);
1772
+ }
1773
+ end() {
1774
+ this.parentLogger._popContext();
1775
+ }
1776
+ debug(...args) {
1777
+ this.parentLogger.debug(...args);
1778
+ }
1779
+ info(...args) {
1780
+ this.parentLogger.info(...args);
1781
+ }
1782
+ warn(...args) {
1783
+ this.parentLogger.warn(...args);
1784
+ }
1785
+ error(...args) {
1786
+ this.parentLogger.error(...args);
1787
+ }
1788
+ success(...args) {
1789
+ this.parentLogger.success(...args);
1790
+ }
1791
+ critical(...args) {
1792
+ this.parentLogger.critical(...args);
1793
+ }
1794
+ }
1795
+ class ExportLogHandler {
1796
+ buffer = [];
1797
+ maxSize;
1798
+ groupDepth = 0;
1799
+ currentGroup;
1800
+ constructor(maxSize = BUFFER_LIMITS.DEFAULT_SIZE) {
1801
+ this.maxSize = Math.min(Math.max(maxSize, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
1802
+ }
1803
+ /**
1804
+ * Handle incoming log and store in buffer
1805
+ */
1806
+ handle(level, message, args, metadata) {
1807
+ const entry = {
1808
+ id: generateLogId(),
1809
+ timestamp: metadata.timestamp,
1810
+ level,
1811
+ prefix: metadata.prefix,
1812
+ message,
1813
+ args,
1814
+ location: metadata.stackInfo,
1815
+ groupInfo: this.groupDepth > 0 ? {
1816
+ depth: this.groupDepth,
1817
+ groupName: this.currentGroup
1818
+ } : void 0
1819
+ };
1820
+ this.buffer.push(entry);
1821
+ if (this.buffer.length > this.maxSize) {
1822
+ this.buffer.shift();
1823
+ }
1824
+ }
1825
+ /**
1826
+ * Set group tracking for nested logs
1827
+ */
1828
+ setGroupInfo(depth, groupName) {
1829
+ this.groupDepth = depth;
1830
+ this.currentGroup = groupName;
1831
+ }
1832
+ /**
1833
+ * Get buffer statistics
1834
+ */
1835
+ getBufferStats() {
1836
+ const levelCounts = this.buffer.reduce((acc, entry) => {
1837
+ const currentCount = acc[entry.level] ? acc[entry.level] : 0;
1838
+ acc[entry.level] = currentCount + 1;
1839
+ return acc;
1840
+ }, {});
1841
+ let oldestLog;
1842
+ let newestLog;
1843
+ if (this.buffer.length > 0) {
1844
+ const firstEntry = this.buffer[0];
1845
+ const lastEntry = this.buffer[this.buffer.length - 1];
1846
+ if (firstEntry && firstEntry.timestamp) {
1847
+ oldestLog = new Date(firstEntry.timestamp);
1848
+ }
1849
+ if (lastEntry && lastEntry.timestamp) {
1850
+ newestLog = new Date(lastEntry.timestamp);
1851
+ }
1852
+ }
1853
+ return {
1854
+ size: this.buffer.length,
1855
+ maxSize: this.maxSize,
1856
+ usage: this.buffer.length / this.maxSize * 100,
1857
+ oldestLog,
1858
+ newestLog,
1859
+ levelCounts: {
1860
+ debug: levelCounts.debug ? levelCounts.debug : 0,
1861
+ info: levelCounts.info ? levelCounts.info : 0,
1862
+ warn: levelCounts.warn ? levelCounts.warn : 0,
1863
+ error: levelCounts.error ? levelCounts.error : 0,
1864
+ critical: levelCounts.critical ? levelCounts.critical : 0
1865
+ }
1866
+ };
1867
+ }
1868
+ /**
1869
+ * Clear the buffer
1870
+ */
1871
+ clearBuffer() {
1872
+ this.buffer = [];
1873
+ }
1874
+ /**
1875
+ * Set buffer size (with limits)
1876
+ */
1877
+ setBufferSize(size) {
1878
+ this.maxSize = Math.min(Math.max(size, BUFFER_LIMITS.MIN_SIZE), BUFFER_LIMITS.MAX_SIZE);
1879
+ if (this.buffer.length > this.maxSize) {
1880
+ this.buffer = this.buffer.slice(-this.maxSize);
1881
+ }
1882
+ }
1883
+ /**
1884
+ * Filter logs based on criteria
1885
+ */
1886
+ filterLogs(filters = {}) {
1887
+ let filtered = [...this.buffer];
1888
+ if (filters.levels?.length) {
1889
+ filtered = filtered.filter((entry) => filters.levels.includes(entry.level));
1890
+ }
1891
+ if (filters.prefixes?.length) {
1892
+ filtered = filtered.filter(
1893
+ (entry) => entry.prefix && filters.prefixes.includes(entry.prefix)
1894
+ );
1895
+ }
1896
+ if (filters.excludePrefixes?.length) {
1897
+ filtered = filtered.filter(
1898
+ (entry) => !entry.prefix || !filters.excludePrefixes.includes(entry.prefix)
1899
+ );
1900
+ }
1901
+ if (filters.since) {
1902
+ const sinceDate = parseTimeInput(filters.since);
1903
+ filtered = filtered.filter((entry) => new Date(entry.timestamp) >= sinceDate);
1904
+ }
1905
+ if (filters.until) {
1906
+ const untilDate = parseTimeInput(filters.until);
1907
+ filtered = filtered.filter((entry) => new Date(entry.timestamp) <= untilDate);
1908
+ }
1909
+ if (filters.withStackTrace) {
1910
+ filtered = filtered.filter((entry) => entry.location);
1911
+ }
1912
+ if (filters.errorsOnly) {
1913
+ filtered = filtered.filter((entry) => entry.level === "error" || entry.level === "critical");
1914
+ }
1915
+ if (filters.search) {
1916
+ const searchTerm = filters.search.toLowerCase();
1917
+ filtered = filtered.filter(
1918
+ (entry) => entry.message.toLowerCase().includes(searchTerm) || entry.args.some(
1919
+ (arg) => String(arg).toLowerCase().includes(searchTerm)
1920
+ )
1921
+ );
1922
+ }
1923
+ if (filters.last) {
1924
+ filtered = filtered.slice(-filters.last);
1925
+ }
1926
+ if (filters.first) {
1927
+ filtered = filtered.slice(0, filters.first);
1928
+ }
1929
+ return filtered;
1930
+ }
1931
+ /**
1932
+ * Export logs in JSON format
1933
+ */
1934
+ exportJSON(logs, options) {
1935
+ const data = logs.map((entry) => ({
1936
+ timestamp: entry.timestamp,
1937
+ level: entry.level,
1938
+ prefix: entry.prefix,
1939
+ message: entry.message,
1940
+ ...options.minimal ? {} : {
1941
+ args: entry.args.slice(1),
1942
+ location: entry.location,
1943
+ groupInfo: entry.groupInfo
1944
+ }
1945
+ }));
1946
+ return options.compact ? JSON.stringify(data) : JSON.stringify(data, null, 2);
1947
+ }
1948
+ /**
1949
+ * Export logs in CSV format
1950
+ */
1951
+ exportCSV(logs, options) {
1952
+ const headers = options.minimal ? ["Timestamp", "Level", "Prefix", "Message"] : ["Timestamp", "Level", "Prefix", "Message", "File", "Line", "Args"];
1953
+ const rows = logs.map((entry) => {
1954
+ const baseRow = [
1955
+ formatDisplayTime(new Date(entry.timestamp), "full"),
1956
+ entry.level.toUpperCase(),
1957
+ entry.prefix || "",
1958
+ `"${entry.message.replace(/"/g, '""')}"`
1959
+ ];
1960
+ if (!options.minimal) {
1961
+ baseRow.push(
1962
+ entry.location?.file || "",
1963
+ entry.location?.line?.toString() || "",
1964
+ `"${safeStringify(entry.args.slice(1)).replace(/"/g, '""')}"`
1965
+ );
1966
+ }
1967
+ return baseRow;
1968
+ });
1969
+ return [headers.join(","), ...rows.map((row) => row.join(","))].join("\n");
1970
+ }
1971
+ /**
1972
+ * Export logs in Markdown format
1973
+ */
1974
+ exportMarkdown(logs, options) {
1975
+ const now = /* @__PURE__ */ new Date();
1976
+ let content = `# Log Export - ${formatDisplayTime(now, "full")}
1977
+
1978
+ `;
1979
+ if (!options.minimal) {
1980
+ const summary = this.getBufferStats();
1981
+ content += `## Summary
1982
+ `;
1983
+ content += `- **Total logs**: ${logs.length}
1984
+ `;
1985
+ content += `- **Errors**: ${summary.levelCounts.error + summary.levelCounts.critical}
1986
+ `;
1987
+ content += `- **Warnings**: ${summary.levelCounts.warn}
1988
+
1989
+ `;
1990
+ }
1991
+ if (options.groupBy === "level") {
1992
+ const grouped = logs.reduce((acc, entry) => {
1993
+ const level = entry.level;
1994
+ if (!acc[level]) {
1995
+ acc[level] = [];
1996
+ }
1997
+ const levelArray = acc[level];
1998
+ if (levelArray) {
1999
+ levelArray.push(entry);
2000
+ }
2001
+ return acc;
2002
+ }, {});
2003
+ Object.entries(grouped).forEach(([level, entries]) => {
2004
+ const emoji = this.getLevelEmoji(level);
2005
+ content += `## ${emoji} ${level.toUpperCase()} (${entries.length})
2006
+
2007
+ `;
2008
+ entries.forEach((entry) => {
2009
+ const time = formatDisplayTime(new Date(entry.timestamp), "time-only");
2010
+ const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
2011
+ const prefix = entry.prefix ? ` **${entry.prefix}**:` : "";
2012
+ content += `- \`${time}\`${prefix} ${entry.message}${location}
2013
+ `;
2014
+ });
2015
+ content += "\n";
2016
+ });
2017
+ } else {
2018
+ content += "## Logs\n\n";
2019
+ logs.forEach((entry) => {
2020
+ const time = formatDisplayTime(new Date(entry.timestamp), "time-only");
2021
+ const emoji = this.getLevelEmoji(entry.level);
2022
+ const location = entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
2023
+ const prefix = entry.prefix ? ` **${entry.prefix}**:` : "";
2024
+ content += `- \`${time}\` ${emoji}${prefix} ${entry.message}${location}
2025
+ `;
2026
+ });
2027
+ }
2028
+ return content;
2029
+ }
2030
+ /**
2031
+ * Export logs in plain text format
2032
+ */
2033
+ exportPlain(logs, options) {
2034
+ return logs.map((entry) => {
2035
+ const time = formatDisplayTime(new Date(entry.timestamp), options.minimal ? "time-only" : "short");
2036
+ const level = entry.level.toUpperCase().padEnd(8);
2037
+ const prefix = entry.prefix ? `[${entry.prefix}] ` : "";
2038
+ const location = !options.minimal && entry.location ? ` (${entry.location.file}:${entry.location.line})` : "";
2039
+ return `${time} ${level} ${prefix}${entry.message}${location}`;
2040
+ }).join("\n");
2041
+ }
2042
+ /**
2043
+ * Export logs in HTML format
2044
+ */
2045
+ exportHTML(logs, _options) {
2046
+ const title = `Log Export - ${formatDisplayTime(/* @__PURE__ */ new Date(), "full")}`;
2047
+ let html = `<!DOCTYPE html>
2048
+ <html lang="en">
2049
+ <head>
2050
+ <meta charset="UTF-8">
2051
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2052
+ <title>${title}</title>
2053
+ <style>
2054
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; line-height: 1.6; }
2055
+ .header { border-bottom: 2px solid #ddd; padding-bottom: 20px; margin-bottom: 20px; }
2056
+ .log-entry { margin: 5px 0; padding: 8px; border-radius: 4px; font-family: 'Monaco', 'Consolas', monospace; }
2057
+ .timestamp { color: #666; font-size: 0.9em; }
2058
+ .level { font-weight: bold; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
2059
+ .prefix { background: #2d3748; color: #e2e8f0; padding: 2px 6px; border-radius: 3px; margin: 0 8px; }
2060
+ .location { color: #718096; font-size: 0.9em; }
2061
+ .debug { background: #f0f4ff; }
2062
+ .info { background: #f0f9ff; }
2063
+ .warn { background: #fffbeb; }
2064
+ .error { background: #fef2f2; }
2065
+ .critical { background: #fef2f2; border-left: 4px solid #dc2626; }
2066
+ .level.debug { background: #667eea; color: white; }
2067
+ .level.info { background: #74b9ff; color: white; }
2068
+ .level.warn { background: #fdcb6e; color: #2d3436; }
2069
+ .level.error { background: #e84393; color: white; }
2070
+ .level.critical { background: #ff3838; color: white; }
2071
+ </style>
2072
+ </head>
2073
+ <body>
2074
+ <div class="header">
2075
+ <h1>${title}</h1>
2076
+ <p>Generated by Advanced Logger v2.0.0</p>
2077
+ </div>
2078
+ <div class="logs">`;
2079
+ logs.forEach((entry) => {
2080
+ const time = formatDisplayTime(new Date(entry.timestamp), "full");
2081
+ const location = entry.location ? ` <span class="location">(${escapeHtml(entry.location.file)}:${entry.location.line})</span>` : "";
2082
+ const prefix = entry.prefix ? ` <span class="prefix">${escapeHtml(entry.prefix)}</span>` : "";
2083
+ html += `
2084
+ <div class="log-entry ${entry.level}">
2085
+ <span class="timestamp">${time}</span>
2086
+ <span class="level ${entry.level}">${entry.level.toUpperCase()}</span>
2087
+ ${prefix}
2088
+ <span class="message">${escapeHtml(entry.message)}</span>
2089
+ ${location}
2090
+ </div>`;
2091
+ });
2092
+ html += `
2093
+ </div>
2094
+ </body>
2095
+ </html>`;
2096
+ return html;
2097
+ }
2098
+ /**
2099
+ * Get emoji for log level
2100
+ */
2101
+ getLevelEmoji(level) {
2102
+ const emojis = {
2103
+ debug: "🐞",
2104
+ info: "ℹ️",
2105
+ warn: "⚠️",
2106
+ error: "❌",
2107
+ critical: "🔥"
2108
+ };
2109
+ return emojis[level] || "";
2110
+ }
2111
+ /**
2112
+ * Main export function
2113
+ */
2114
+ export(format, filters = {}, options = {}) {
2115
+ const filteredLogs = this.filterLogs(filters);
2116
+ let data;
2117
+ switch (format) {
2118
+ case "json":
2119
+ data = this.exportJSON(filteredLogs, options);
2120
+ break;
2121
+ case "csv":
2122
+ data = this.exportCSV(filteredLogs, options);
2123
+ break;
2124
+ case "markdown":
2125
+ data = this.exportMarkdown(filteredLogs, options);
2126
+ break;
2127
+ case "plain":
2128
+ data = this.exportPlain(filteredLogs, options);
2129
+ break;
2130
+ case "html":
2131
+ data = this.exportHTML(filteredLogs, options);
2132
+ break;
2133
+ default:
2134
+ throw new Error(`Unsupported export format: ${format}`);
2135
+ }
2136
+ return {
2137
+ format,
2138
+ data,
2139
+ metadata: {
2140
+ totalLogs: this.buffer.length,
2141
+ filteredLogs: filteredLogs.length,
2142
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
2143
+ filters,
2144
+ options
2145
+ }
2146
+ };
2147
+ }
2148
+ /**
2149
+ * Copy to clipboard with fallback
2150
+ */
2151
+ async copyToClipboard(format, filters = {}, options = {}) {
2152
+ const result = this.export(format, filters, options);
2153
+ try {
2154
+ if (navigator.clipboard && window.isSecureContext) {
2155
+ await navigator.clipboard.writeText(result.data);
2156
+ return true;
2157
+ } else {
2158
+ const textArea = document.createElement("textarea");
2159
+ textArea.value = result.data;
2160
+ textArea.style.position = "fixed";
2161
+ textArea.style.opacity = "0";
2162
+ document.body.appendChild(textArea);
2163
+ textArea.focus();
2164
+ textArea.select();
2165
+ const success = document.execCommand("copy");
2166
+ document.body.removeChild(textArea);
2167
+ return success;
2168
+ }
2169
+ } catch (error) {
2170
+ console.error("Failed to copy to clipboard:", error);
2171
+ return false;
2172
+ }
2173
+ }
2174
+ /**
2175
+ * Get all logs (for debugging)
2176
+ */
2177
+ getAllLogs() {
2178
+ return [...this.buffer];
2179
+ }
2180
+ /**
2181
+ * Save export to file with download prompt
2182
+ */
2183
+ async saveToFile(format, filters = {}, options = {}) {
2184
+ try {
2185
+ const result = this.export(format, filters, options);
2186
+ const blob = new Blob([result.data], {
2187
+ type: this.getMimeType(format)
2188
+ });
2189
+ const url = URL.createObjectURL(blob);
2190
+ const a = document.createElement("a");
2191
+ const filename = this.generateFilename(format, filters);
2192
+ a.href = url;
2193
+ a.download = filename;
2194
+ a.style.display = "none";
2195
+ document.body.appendChild(a);
2196
+ a.click();
2197
+ document.body.removeChild(a);
2198
+ URL.revokeObjectURL(url);
2199
+ return true;
2200
+ } catch (error) {
2201
+ console.error("Failed to save file:", error);
2202
+ return false;
2203
+ }
2204
+ }
2205
+ /**
2206
+ * Get MIME type for format
2207
+ */
2208
+ getMimeType(format) {
2209
+ const mimeTypes = {
2210
+ json: "application/json",
2211
+ csv: "text/csv",
2212
+ markdown: "text/markdown",
2213
+ plain: "text/plain",
2214
+ html: "text/html"
2215
+ };
2216
+ return mimeTypes[format] || "text/plain";
2217
+ }
2218
+ /**
2219
+ * Generate filename with timestamp
2220
+ */
2221
+ generateFilename(format, filters) {
2222
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, -5);
2223
+ const prefix = filters.prefixes?.length === 1 ? `_${filters.prefixes[0]}` : "";
2224
+ const extension = format === "markdown" ? "md" : format;
2225
+ return `logs${prefix}_${timestamp}.${extension}`;
2226
+ }
2227
+ /**
2228
+ * Stream logs to external endpoint
2229
+ */
2230
+ async streamToEndpoint(endpoint, filters = {}, options = {}) {
2231
+ try {
2232
+ const logs = this.filterLogs(filters);
2233
+ const batchSize = options.batchSize || 100;
2234
+ const format = options.format || "json";
2235
+ for (let i = 0; i < logs.length; i += batchSize) {
2236
+ const batch = logs.slice(i, i + batchSize);
2237
+ const result = this.export(format, {}, { compact: true });
2238
+ const headers = {
2239
+ "Content-Type": "application/json"
2240
+ };
2241
+ if (options.apiKey) {
2242
+ headers["Authorization"] = `Bearer ${options.apiKey}`;
2243
+ }
2244
+ const response = await fetch(endpoint, {
2245
+ method: "POST",
2246
+ headers,
2247
+ body: JSON.stringify({
2248
+ logs: batch,
2249
+ metadata: {
2250
+ batchIndex: Math.floor(i / batchSize),
2251
+ totalBatches: Math.ceil(logs.length / batchSize),
2252
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2253
+ }
2254
+ })
2255
+ });
2256
+ if (!response.ok) {
2257
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
2258
+ }
2259
+ }
2260
+ return true;
2261
+ } catch (error) {
2262
+ console.error("Failed to stream logs:", error);
2263
+ return false;
2264
+ }
2265
+ }
2266
+ /**
2267
+ * Create export with metadata enrichment
2268
+ */
2269
+ exportWithMetadata(format, filters = {}, options = {}) {
2270
+ const baseResult = this.export(format, filters, options);
2271
+ const bufferStats = this.getBufferStats();
2272
+ return {
2273
+ ...baseResult,
2274
+ metadata: {
2275
+ ...baseResult.metadata,
2276
+ bufferStats,
2277
+ performance: {
2278
+ memoryUsage: this.estimateMemoryUsage(),
2279
+ processingTime: Date.now()
2280
+ },
2281
+ system: {
2282
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "Node.js",
2283
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2284
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
2285
+ }
2286
+ }
2287
+ };
2288
+ }
2289
+ /**
2290
+ * Estimate memory usage of buffer
2291
+ */
2292
+ estimateMemoryUsage() {
2293
+ const sampleEntry = this.buffer[0];
2294
+ if (!sampleEntry) return 0;
2295
+ const sampleSize = JSON.stringify(sampleEntry).length;
2296
+ return sampleSize * this.buffer.length;
2297
+ }
2298
+ }
2299
+ class CommandProcessor {
2300
+ commands = /* @__PURE__ */ new Map();
2301
+ aliases = /* @__PURE__ */ new Map();
2302
+ plugins = /* @__PURE__ */ new Map();
2303
+ history = [];
2304
+ maxHistorySize = 100;
2305
+ isInteractiveMode = false;
2306
+ /**
2307
+ * Register a command
2308
+ */
2309
+ registerCommand(command) {
2310
+ this.commands.set(command.name, command);
2311
+ if (command.aliases) {
2312
+ for (const alias of command.aliases) {
2313
+ this.aliases.set(alias, command.name);
2314
+ }
2315
+ }
2316
+ }
2317
+ /**
2318
+ * Register a plugin
2319
+ */
2320
+ registerPlugin(plugin, logger) {
2321
+ if (this.plugins.has(plugin.name)) {
2322
+ throw new Error(`Plugin ${plugin.name} is already registered`);
2323
+ }
2324
+ this.plugins.set(plugin.name, plugin);
2325
+ for (const command of plugin.commands) {
2326
+ this.registerCommand(command);
2327
+ }
2328
+ if (plugin.initialize && logger) {
2329
+ plugin.initialize(this, logger);
2330
+ }
2331
+ }
2332
+ /**
2333
+ * Unregister a plugin
2334
+ */
2335
+ unregisterPlugin(pluginName) {
2336
+ const plugin = this.plugins.get(pluginName);
2337
+ if (!plugin) return;
2338
+ for (const command of plugin.commands) {
2339
+ this.commands.delete(command.name);
2340
+ if (command.aliases) {
2341
+ for (const alias of command.aliases) {
2342
+ this.aliases.delete(alias);
2343
+ }
2344
+ }
2345
+ }
2346
+ if (plugin.cleanup) {
2347
+ plugin.cleanup();
2348
+ }
2349
+ this.plugins.delete(pluginName);
2350
+ }
2351
+ /**
2352
+ * Get all registered commands
2353
+ */
2354
+ getCommands() {
2355
+ return Array.from(this.commands.values());
2356
+ }
2357
+ /**
2358
+ * Get a specific command
2359
+ */
2360
+ getCommand(name) {
2361
+ let command = this.commands.get(name);
2362
+ if (command) return command;
2363
+ const aliasTarget = this.aliases.get(name);
2364
+ if (aliasTarget) {
2365
+ return this.commands.get(aliasTarget);
2366
+ }
2367
+ return void 0;
2368
+ }
2369
+ /**
2370
+ * Get command history
2371
+ */
2372
+ getHistory() {
2373
+ return [...this.history];
2374
+ }
2375
+ /**
2376
+ * Clear command history
2377
+ */
2378
+ clearHistory() {
2379
+ this.history = [];
2380
+ }
2381
+ /**
2382
+ * Get registered plugins
2383
+ */
2384
+ getPlugins() {
2385
+ return Array.from(this.plugins.values());
2386
+ }
2387
+ /**
2388
+ * Enter interactive mode
2389
+ */
2390
+ enterInteractiveMode(logger) {
2391
+ this.isInteractiveMode = true;
2392
+ logger.info("🔧 Interactive CLI mode activated. Type /exit to quit, /help for commands.");
2393
+ if (typeof window !== "undefined") {
2394
+ this.setupBrowserInteractiveMode(logger);
2395
+ }
2396
+ }
2397
+ /**
2398
+ * Exit interactive mode
2399
+ */
2400
+ exitInteractiveMode() {
2401
+ this.isInteractiveMode = false;
2402
+ }
2403
+ /**
2404
+ * Setup browser interactive mode
2405
+ */
2406
+ setupBrowserInteractiveMode(logger) {
2407
+ window.cli = (commandString) => {
2408
+ return this.processCommand(`/${commandString}`, logger);
2409
+ };
2410
+ logger.info('💡 Use cli("command") to execute CLI commands in browser console.');
2411
+ }
2412
+ /**
2413
+ * Process a CLI command
2414
+ */
2415
+ async processCommand(commandString, logger) {
2416
+ if (!commandString.startsWith("/")) {
2417
+ logger.error("Invalid command. Commands must start with /");
2418
+ this.addToHistory(commandString, false);
2419
+ return;
2420
+ }
2421
+ const parts = commandString.slice(1).split(" ");
2422
+ const commandName = parts[0] || "";
2423
+ const args = parts.slice(1).join(" ");
2424
+ const command = this.getCommand(commandName);
2425
+ if (!command) {
2426
+ logger.error(`Unknown command: ${commandName}. Type /help for available commands.`);
2427
+ const suggestions = this.getSuggestions(commandName);
2428
+ if (suggestions.length > 0) {
2429
+ logger.info(`📋 Did you mean: ${suggestions.slice(0, 3).join(", ")}?`);
2430
+ }
2431
+ this.addToHistory(commandString, false);
2432
+ return;
2433
+ }
2434
+ try {
2435
+ await command.execute(args || "", logger);
2436
+ this.addToHistory(commandString, true);
2437
+ } catch (error) {
2438
+ logger.error(`Command '${commandName}' failed:`, error);
2439
+ this.addToHistory(commandString, false);
2440
+ }
2441
+ }
2442
+ /**
2443
+ * Add command to history
2444
+ */
2445
+ addToHistory(command, success) {
2446
+ this.history.unshift({
2447
+ command,
2448
+ timestamp: /* @__PURE__ */ new Date(),
2449
+ success
2450
+ });
2451
+ if (this.history.length > this.maxHistorySize) {
2452
+ this.history = this.history.slice(0, this.maxHistorySize);
2453
+ }
2454
+ }
2455
+ /**
2456
+ * Get command suggestions for partial matches
2457
+ */
2458
+ getSuggestions(partial) {
2459
+ const commandNames = Array.from(this.commands.keys());
2460
+ return commandNames.filter((name) => name.startsWith(partial));
2461
+ }
2462
+ }
2463
+ class ConfigCommand {
2464
+ name = "config";
2465
+ description = "Show or update logger configuration";
2466
+ usage = "/config [json|key=value,...]";
2467
+ execute(args, logger) {
2468
+ if (!args) {
2469
+ this.showStatus(logger);
2470
+ return;
2471
+ }
2472
+ try {
2473
+ if (args.startsWith("{")) {
2474
+ const config = JSON.parse(args);
2475
+ this.applyConfig(config, logger);
2476
+ } else {
2477
+ const pairs = args.split(",").map((pair) => pair.trim().split("="));
2478
+ const config = {};
2479
+ pairs.forEach(([key, value]) => {
2480
+ if (key && value) {
2481
+ config[key.trim()] = value.trim().replace(/["']/g, "");
2482
+ }
2483
+ });
2484
+ this.applyConfig(config, logger);
2485
+ }
2486
+ } catch (error) {
2487
+ logger.error("Invalid config format. Use JSON or key=value pairs:", error);
2488
+ logger.info('Examples: /config {"theme":"dark"} or /config theme=neon,verbosity=debug');
2489
+ }
2490
+ }
2491
+ showStatus(logger) {
2492
+ const statusData = {
2493
+ theme: logger.getConfig().theme || "default",
2494
+ verbosity: logger.getConfig().verbosity,
2495
+ colors: logger.getConfig().enableColors,
2496
+ timestamps: logger.getConfig().enableTimestamps,
2497
+ stackTrace: logger.getConfig().enableStackTrace,
2498
+ globalPrefix: logger.getConfig().globalPrefix || "none",
2499
+ bannerType: logger.getConfig().bannerType || "simple",
2500
+ handlers: logger.getHandlers().length
2501
+ };
2502
+ logger.group("⚙️ Logger Configuration");
2503
+ logger.table(statusData);
2504
+ logger.groupEnd();
2505
+ }
2506
+ applyConfig(config, logger) {
2507
+ const validKeys = ["theme", "verbosity", "enableColors", "enableTimestamps", "enableStackTrace", "globalPrefix", "bannerType"];
2508
+ const applied = [];
2509
+ Object.entries(config).forEach(([key, value]) => {
2510
+ if (validKeys.includes(key)) {
2511
+ if (key === "theme" && typeof value === "string") {
2512
+ logger.setTheme(value);
2513
+ applied.push(`${key}=${value}`);
2514
+ } else if (key === "bannerType" && typeof value === "string") {
2515
+ logger.setBannerType(value);
2516
+ applied.push(`${key}=${value}`);
2517
+ } else if (key === "verbosity") {
2518
+ logger.setVerbosity(value);
2519
+ applied.push(`${key}=${value}`);
2520
+ } else if (key === "globalPrefix") {
2521
+ logger.setGlobalPrefix(value);
2522
+ applied.push(`${key}=${value}`);
2523
+ } else {
2524
+ logger.updateConfig({ [key]: value });
2525
+ applied.push(`${key}=${value}`);
2526
+ }
2527
+ } else {
2528
+ logger.warn(`Invalid config key: ${key}`);
2529
+ }
2530
+ });
2531
+ if (applied.length > 0) {
2532
+ logger.success(`Configuration updated: ${applied.join(", ")}`);
2533
+ }
2534
+ }
2535
+ }
2536
+ class ThemesCommand {
2537
+ name = "themes";
2538
+ description = "Show available theme presets";
2539
+ usage = "/themes";
2540
+ execute(_args, logger) {
2541
+ logger.group("🎨 Available Themes");
2542
+ Object.keys(THEME_PRESETS).forEach((themeName) => {
2543
+ const preview = THEME_PRESETS[themeName];
2544
+ const previewStyle = new StyleBuilder().bg(preview.info.background).color(preview.info.color).padding("4px 8px").rounded("4px").border(preview.info.border).build();
2545
+ console.log(`%c${themeName}`, previewStyle, `- ${themeName} theme preview`);
2546
+ });
2547
+ logger.groupEnd();
2548
+ }
2549
+ }
2550
+ class BannersCommand {
2551
+ name = "banners";
2552
+ description = "Show available banner types";
2553
+ usage = "/banners";
2554
+ execute(_args, logger) {
2555
+ logger.group("🖼️ Available Banner Types");
2556
+ Object.keys(BANNER_VARIANTS).forEach((bannerName) => {
2557
+ const banner = BANNER_VARIANTS[bannerName];
2558
+ console.log(`%c${bannerName}`, "font-weight: bold; color: #667eea;");
2559
+ console.log(`%cPreview:`, "color: #666; font-size: 12px;");
2560
+ if (bannerName === "simple") {
2561
+ console.log(`%c${banner.text}`, banner.style);
2562
+ } else if (bannerName === "ascii") {
2563
+ console.log(`%c${banner.text.split("\n").slice(1, 4).join("\n")}...`, "font-family: monospace; color: #667eea; font-size: 10px;");
2564
+ } else if (bannerName === "unicode") {
2565
+ console.log(`%c${banner.text}`, banner.style);
2566
+ } else {
2567
+ console.log(`%c${bannerName} banner`, "color: #666; font-style: italic;");
2568
+ }
2569
+ });
2570
+ logger.groupEnd();
2571
+ }
2572
+ }
2573
+ class BannerCommand {
2574
+ name = "banner";
2575
+ description = "Change or show current banner type";
2576
+ usage = "/banner [type]";
2577
+ execute(args, logger) {
2578
+ if (!args) {
2579
+ logger.showBanner();
2580
+ return;
2581
+ }
2582
+ if (args in BANNER_VARIANTS) {
2583
+ logger.setBannerType(args);
2584
+ logger.showBanner();
2585
+ } else {
2586
+ logger.error(`Invalid banner type: ${args}. Available: ${Object.keys(BANNER_VARIANTS).join(", ")}`);
2587
+ }
2588
+ }
2589
+ }
2590
+ class StatusCommand {
2591
+ name = "status";
2592
+ description = "Show current logger status and configuration";
2593
+ usage = "/status";
2594
+ execute(_args, logger) {
2595
+ const config = logger.getConfig();
2596
+ const statusData = {
2597
+ theme: config.theme ? config.theme : "default",
2598
+ verbosity: config.verbosity,
2599
+ colors: config.enableColors,
2600
+ timestamps: config.enableTimestamps,
2601
+ stackTrace: config.enableStackTrace,
2602
+ globalPrefix: config.globalPrefix ? config.globalPrefix : "none",
2603
+ bannerType: config.bannerType ? config.bannerType : "simple",
2604
+ handlers: logger.getHandlers().length,
2605
+ bufferSize: config.bufferSize ? config.bufferSize : 1e3
2606
+ };
2607
+ logger.group("⚙️ Logger Configuration");
2608
+ logger.table(statusData);
2609
+ logger.groupEnd();
2610
+ const exportHandler = logger.getExportHandler();
2611
+ if (exportHandler) {
2612
+ const bufferStats = exportHandler.getBufferStats();
2613
+ logger.group("📊 Buffer Statistics");
2614
+ logger.table({
2615
+ size: `${bufferStats.size}/${bufferStats.maxSize}`,
2616
+ usage: `${bufferStats.usage.toFixed(1)}%`,
2617
+ oldestLog: bufferStats.oldestLog ? bufferStats.oldestLog.toISOString() : "None",
2618
+ newestLog: bufferStats.newestLog ? bufferStats.newestLog.toISOString() : "None",
2619
+ errorCount: bufferStats.levelCounts.error + bufferStats.levelCounts.critical,
2620
+ warningCount: bufferStats.levelCounts.warn
2621
+ });
2622
+ logger.groupEnd();
2623
+ }
2624
+ }
2625
+ }
2626
+ class ResetCommand {
2627
+ name = "reset";
2628
+ description = "Reset logger configuration to defaults";
2629
+ usage = "/reset";
2630
+ execute(_args, logger) {
2631
+ logger.resetConfig();
2632
+ }
2633
+ }
2634
+ class DemoCommand {
2635
+ name = "demo";
2636
+ description = "Show comprehensive feature demonstration";
2637
+ usage = "/demo";
2638
+ execute(_args, logger) {
2639
+ logger.group("🎪 Advanced Logger Demo");
2640
+ logger.debug("Debug message with detailed information");
2641
+ logger.info("Informational message about system state");
2642
+ logger.warn("Warning about deprecated feature");
2643
+ logger.error("Error processing user request");
2644
+ logger.success("Operation completed successfully");
2645
+ logger.critical("Critical system failure detected");
2646
+ logger.group("📊 Advanced Features Demo");
2647
+ logger.table([
2648
+ { feature: "Styled Console", status: "✅ Active", performance: "Excellent" },
2649
+ { feature: "Theme System", status: "✅ Active", performance: "Great" },
2650
+ { feature: "CLI Interface", status: "✅ Active", performance: "Good" },
2651
+ { feature: "Export System", status: "✅ Active", performance: "Excellent" }
2652
+ ]);
2653
+ logger.time("demo-operation");
2654
+ setTimeout(() => {
2655
+ logger.timeEnd("demo-operation");
2656
+ }, 100);
2657
+ logger.logWithSVG("SVG Demo");
2658
+ logger.logAnimated("🌟 Animated Logger Demo 🌟", 2);
2659
+ logger.groupEnd();
2660
+ logger.groupEnd();
2661
+ logger.info("Demo completed! Check the console for styled output.");
2662
+ }
2663
+ }
2664
+ function parseArguments(args) {
2665
+ const filters = {};
2666
+ const options = {};
2667
+ let format;
2668
+ if (!args.trim()) return { filters, options };
2669
+ const argParts = args.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
2670
+ for (let i = 0; i < argParts.length; i++) {
2671
+ const arg = argParts[i];
2672
+ if (!arg) {
2673
+ continue;
2674
+ }
2675
+ if (i === 0 && !arg.startsWith("--") && arg in EXPORT_FORMATS) {
2676
+ format = arg;
2677
+ continue;
2678
+ }
2679
+ if (arg.startsWith("--")) {
2680
+ const [flag, value] = arg.slice(2).split("=");
2681
+ switch (flag) {
2682
+ case "level":
2683
+ case "levels":
2684
+ if (value) {
2685
+ filters.levels = value.split(",").map((l) => l.trim());
2686
+ }
2687
+ break;
2688
+ case "since":
2689
+ if (value) filters.since = value;
2690
+ break;
2691
+ case "until":
2692
+ if (value) filters.until = value;
2693
+ break;
2694
+ case "prefix":
2695
+ case "prefixes":
2696
+ if (value) {
2697
+ filters.prefixes = value.split(",").map((p) => p.trim());
2698
+ }
2699
+ break;
2700
+ case "exclude-prefix":
2701
+ case "exclude-prefixes":
2702
+ if (value) {
2703
+ filters.excludePrefixes = value.split(",").map((p) => p.trim());
2704
+ }
2705
+ break;
2706
+ case "last":
2707
+ if (value) filters.last = parseInt(value, 10);
2708
+ break;
2709
+ case "first":
2710
+ if (value) filters.first = parseInt(value, 10);
2711
+ break;
2712
+ case "search":
2713
+ if (value) filters.search = value.replace(/['"]/g, "");
2714
+ break;
2715
+ case "with-stack":
2716
+ filters.withStackTrace = true;
2717
+ break;
2718
+ case "errors-only":
2719
+ filters.errorsOnly = true;
2720
+ break;
2721
+ case "group-by":
2722
+ if (value) {
2723
+ filters.groupBy = value;
2724
+ options.groupBy = value;
2725
+ }
2726
+ break;
2727
+ case "minimal":
2728
+ options.minimal = true;
2729
+ break;
2730
+ case "compact":
2731
+ options.compact = true;
2732
+ break;
2733
+ case "styled":
2734
+ options.styled = true;
2735
+ break;
2736
+ }
2737
+ }
2738
+ }
2739
+ return { filters, options, format };
2740
+ }
2741
+ class ExportCommand {
2742
+ name = "export";
2743
+ description = "Export logs to various formats";
2744
+ usage = "/export <format> [--filter=value] [--option]";
2745
+ execute(args, logger) {
2746
+ const exportHandler = logger.getExportHandler();
2747
+ if (!exportHandler) {
2748
+ logger.error("Export handler not available. Make sure ExportLogHandler is registered.");
2749
+ return;
2750
+ }
2751
+ const { filters, options, format } = parseArguments(args);
2752
+ if (!format) {
2753
+ logger.error("Format required. Available formats: " + Object.keys(EXPORT_FORMATS).join(", "));
2754
+ logger.info("Usage: /export <format> [--filter=value]");
2755
+ logger.info("Example: /export json --level=error,warn --last=50");
2756
+ return;
2757
+ }
2758
+ try {
2759
+ const result = exportHandler.export(format, filters, options);
2760
+ logger.success(`✅ Export completed: ${result.metadata.filteredLogs} logs exported in ${format} format`);
2761
+ if (result.data.length < 1e3) {
2762
+ logger.group(`📄 Preview (${format.toUpperCase()})`);
2763
+ console.log(result.data);
2764
+ logger.groupEnd();
2765
+ } else {
2766
+ logger.info(`📄 Export size: ${(result.data.length / 1024).toFixed(2)}KB`);
2767
+ }
2768
+ logger.table({
2769
+ format: result.format,
2770
+ totalLogs: result.metadata.totalLogs,
2771
+ filtered: result.metadata.filteredLogs,
2772
+ exported: result.metadata.exportedAt
2773
+ });
2774
+ } catch (error) {
2775
+ logger.error("Export failed:", error);
2776
+ }
2777
+ }
2778
+ }
2779
+ class CopyCommand {
2780
+ name = "copy";
2781
+ description = "Copy logs to clipboard";
2782
+ usage = "/copy <format> [--filter=value] [--option]";
2783
+ async execute(args, logger) {
2784
+ const exportHandler = logger.getExportHandler();
2785
+ if (!exportHandler) {
2786
+ logger.error("Export handler not available. Make sure ExportLogHandler is registered.");
2787
+ return;
2788
+ }
2789
+ const { filters, options, format } = parseArguments(args);
2790
+ if (!format) {
2791
+ logger.error("Format required. Available formats: " + Object.keys(EXPORT_FORMATS).join(", "));
2792
+ logger.info("Usage: /copy <format> [--filter=value]");
2793
+ logger.info("Example: /copy plain --level=error --last=25");
2794
+ return;
2795
+ }
2796
+ try {
2797
+ const success = await exportHandler.copyToClipboard(format, filters, options);
2798
+ if (success) {
2799
+ const result = exportHandler.export(format, filters, options);
2800
+ logger.success(`📋 Copied ${result.metadata.filteredLogs} logs to clipboard (${format} format)`);
2801
+ } else {
2802
+ logger.error("Failed to copy to clipboard. Browser may not support clipboard API.");
2803
+ }
2804
+ } catch (error) {
2805
+ logger.error("Copy failed:", error);
2806
+ }
2807
+ }
2808
+ }
2809
+ class BufferSizeCommand {
2810
+ name = "buffer-size";
2811
+ description = "Set log buffer size";
2812
+ usage = "/buffer-size <size>";
2813
+ execute(args, logger) {
2814
+ const exportHandler = logger.getExportHandler();
2815
+ if (!exportHandler) {
2816
+ logger.error("Export handler not available.");
2817
+ return;
2818
+ }
2819
+ const size = parseInt(args.trim(), 10);
2820
+ if (isNaN(size) || size <= 0) {
2821
+ logger.error("Invalid buffer size. Must be a positive number.");
2822
+ logger.info("Example: /buffer-size 2000");
2823
+ return;
2824
+ }
2825
+ exportHandler.setBufferSize(size);
2826
+ logger.success(`Buffer size set to ${size}`);
2827
+ }
2828
+ }
2829
+ class ClearBufferCommand {
2830
+ name = "clear-buffer";
2831
+ description = "Clear the log buffer";
2832
+ usage = "/clear-buffer";
2833
+ execute(_args, logger) {
2834
+ const exportHandler = logger.getExportHandler();
2835
+ if (!exportHandler) {
2836
+ logger.error("Export handler not available.");
2837
+ return;
2838
+ }
2839
+ const stats = exportHandler.getBufferStats();
2840
+ exportHandler.clearBuffer();
2841
+ logger.success(`✅ Buffer cleared. Removed ${stats.size} log entries.`);
2842
+ }
2843
+ }
2844
+ class BufferInfoCommand {
2845
+ name = "buffer-info";
2846
+ description = "Show buffer statistics and information";
2847
+ usage = "/buffer-info";
2848
+ execute(_args, logger) {
2849
+ const exportHandler = logger.getExportHandler();
2850
+ if (!exportHandler) {
2851
+ logger.error("Export handler not available.");
2852
+ return;
2853
+ }
2854
+ const stats = exportHandler.getBufferStats();
2855
+ logger.group("📊 Buffer Information");
2856
+ logger.table({
2857
+ size: `${stats.size}/${stats.maxSize}`,
2858
+ usage: `${stats.usage.toFixed(1)}%`,
2859
+ oldestLog: stats.oldestLog?.toLocaleString() || "None",
2860
+ newestLog: stats.newestLog?.toLocaleString() || "None"
2861
+ });
2862
+ logger.group("📈 Log Level Counts");
2863
+ logger.table(stats.levelCounts);
2864
+ logger.groupEnd();
2865
+ logger.groupEnd();
2866
+ }
2867
+ }
2868
+ class HelpCommand {
2869
+ name = "help";
2870
+ description = "Show CLI help and available commands";
2871
+ usage = "/help [command]";
2872
+ execute(_args, logger) {
2873
+ const helpStyle = new StyleBuilder().bg("linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%)").color("#495057").padding("15px 20px").rounded("8px").border("1px solid #dee2e6").font("Monaco, Consolas, monospace").size("13px").build();
2874
+ const helpText = `
2875
+ ╭─────────────── ADVANCED LOGGER CLI COMMANDS ─────────────────╮
2876
+ │ │
2877
+ │ CONFIGURATION │
2878
+ │ /config Show current configuration │
2879
+ │ /config {json} Apply JSON configuration │
2880
+ │ /config key=val Apply key-value configuration │
2881
+ │ /themes Show available themes │
2882
+ │ /banners Show available banner types │
2883
+ │ /banner [type] Change/show banner type │
2884
+ │ /status Show logger status & buffer stats │
2885
+ │ /demo Show feature demonstration │
2886
+ │ /reset Reset to default configuration │
2887
+ │ │
2888
+ │ EXPORT & CLIPBOARD │
2889
+ │ /export <format> Export logs (json|csv|md|plain|html) │
2890
+ │ /copy <format> Copy logs to clipboard │
2891
+ │ /buffer-size N Set log buffer size │
2892
+ │ /buffer-info Show buffer statistics │
2893
+ │ /clear-buffer Clear stored logs │
2894
+ │ │
2895
+ │ EXPORT FILTERS (for export/copy commands) │
2896
+ │ --level error,warn Filter by log levels │
2897
+ │ --since 2h Logs from last 2 hours │
2898
+ │ --until 1h Logs until 1 hour ago │
2899
+ │ --prefix API,DB Filter by prefixes │
2900
+ │ --exclude-prefix INT Exclude prefixes │
2901
+ │ --last 50 Last 50 logs only │
2902
+ │ --first 25 First 25 logs only │
2903
+ │ --search "error" Search in log messages │
2904
+ │ --with-stack Only logs with stack traces │
2905
+ │ --errors-only Only error + critical logs │
2906
+ │ --group-by level Group by level/prefix/hour │
2907
+ │ │
2908
+ │ EXPORT OPTIONS │
2909
+ │ --minimal Minimal output format │
2910
+ │ --compact Remove extra whitespace │
2911
+ │ --styled Include styling (HTML format) │
2912
+ │ │
2913
+ ├──────────────────── CONFIGURATION OPTIONS ─────────────────┤
2914
+ │ │
2915
+ │ theme: default | dark | light | neon | minimal | cyberpunk│
2916
+ │ bannerType: simple | ascii | unicode | svg | animated │
2917
+ │ verbosity: debug | info | warn | error | critical | silent│
2918
+ │ enableColors: true | false │
2919
+ │ enableTimestamps: true | false │
2920
+ │ enableStackTrace: true | false │
2921
+ │ globalPrefix: "string" │
2922
+ │ bufferSize: number (50-10000) │
2923
+ │ │
2924
+ ├──────────────────────── EXAMPLES ──────────────────────────┤
2925
+ │ │
2926
+ │ Basic Configuration: │
2927
+ │ /config {"theme":"dark","verbosity":"debug"} │
2928
+ │ /config theme=neon,bufferSize=2000 │
2929
+ │ /banner animated Change to animated banner │
2930
+ │ │
2931
+ │ Export Examples: │
2932
+ │ /export json --level=error,warn --last=25 │
2933
+ │ /export csv --since=2h --prefix=API │
2934
+ │ /export markdown --group-by=level --errors-only │
2935
+ │ /export html --styled --since=1h │
2936
+ │ │
2937
+ │ Clipboard Examples: │
2938
+ │ /copy plain --minimal --last=10 │
2939
+ │ /copy json --search="authentication" --compact │
2940
+ │ /copy csv --since=30m --exclude-prefix=DEBUG │
2941
+ │ │
2942
+ │ Buffer Management: │
2943
+ │ /buffer-size 5000 Increase buffer to 5000 logs │
2944
+ │ /buffer-info Show detailed buffer statistics │
2945
+ │ /clear-buffer Clear all stored logs │
2946
+ │ │
2947
+ │ Time Formats: │
2948
+ │ --since=2h 2 hours ago │
2949
+ │ --since=30m 30 minutes ago │
2950
+ │ --since=1d 1 day ago │
2951
+ │ --since="2024-01-01T10:00:00Z" Specific ISO date │
2952
+ │ │
2953
+ ╰─────────────────────────────────────────────────────────────╯`;
2954
+ console.log(`%c${helpText}`, helpStyle);
2955
+ logger.group("💡 Quick Tips");
2956
+ const tips = [
2957
+ "Use /demo to see all logger features in action",
2958
+ "Logs are automatically stored in a circular buffer for export",
2959
+ "Export formats: JSON (structured), CSV (Excel), Markdown (readable), Plain (simple), HTML (styled)",
2960
+ "Time filters support relative (2h, 30m) and absolute (ISO) formats",
2961
+ 'Combine multiple filters: /export json --level=error --since=1h --search="auth"',
2962
+ "Use /copy for quick clipboard access instead of /export"
2963
+ ];
2964
+ tips.forEach((tip) => {
2965
+ logger.info(`• ${tip}`);
2966
+ });
2967
+ logger.groupEnd();
2968
+ }
2969
+ }
2970
+ class HistoryCommand {
2971
+ name = "history";
2972
+ description = "Show command execution history";
2973
+ usage = "/history [limit] - Show recent commands (default: 10)";
2974
+ category = "system";
2975
+ aliases = ["hist", "h"];
2976
+ execute(args, logger) {
2977
+ const processor = logger.cliProcessor;
2978
+ if (!processor) {
2979
+ logger.error("CLI processor not available");
2980
+ return;
2981
+ }
2982
+ const limit = parseInt(args) || 10;
2983
+ const history = processor.getHistory().slice(0, limit);
2984
+ if (history.length === 0) {
2985
+ logger.info("📝 No command history available");
2986
+ return;
2987
+ }
2988
+ logger.info(`📋 Last ${history.length} commands:`);
2989
+ history.forEach((entry, index) => {
2990
+ const status = entry.success ? "✅" : "❌";
2991
+ const time = entry.timestamp.toLocaleTimeString();
2992
+ logger.info(`${status} [${time}] ${entry.command}`);
2993
+ });
2994
+ }
2995
+ }
2996
+ class ClearHistoryCommand {
2997
+ name = "clearhistory";
2998
+ description = "Clear command execution history";
2999
+ usage = "/clearhistory - Remove all command history";
3000
+ category = "system";
3001
+ aliases = ["clrhist"];
3002
+ execute(args, logger) {
3003
+ const processor = logger.cliProcessor;
3004
+ if (!processor) {
3005
+ logger.error("CLI processor not available");
3006
+ return;
3007
+ }
3008
+ processor.clearHistory();
3009
+ logger.success("🗑️ Command history cleared");
3010
+ }
3011
+ }
3012
+ class InteractiveCommand {
3013
+ name = "interactive";
3014
+ description = "Enter interactive CLI mode";
3015
+ usage = "/interactive - Start interactive command mode";
3016
+ category = "system";
3017
+ aliases = ["i", "repl"];
3018
+ execute(args, logger) {
3019
+ const processor = logger.cliProcessor;
3020
+ if (!processor) {
3021
+ logger.error("CLI processor not available");
3022
+ return;
3023
+ }
3024
+ processor.enterInteractiveMode(logger);
3025
+ }
3026
+ }
3027
+ class PluginsCommand {
3028
+ name = "plugins";
3029
+ description = "List loaded CLI plugins";
3030
+ usage = "/plugins - Show all registered plugins";
3031
+ category = "system";
3032
+ aliases = ["plug"];
3033
+ execute(args, logger) {
3034
+ const processor = logger.cliProcessor;
3035
+ if (!processor) {
3036
+ logger.error("CLI processor not available");
3037
+ return;
3038
+ }
3039
+ const plugins = processor.getPlugins();
3040
+ if (plugins.length === 0) {
3041
+ logger.info("🔌 No plugins registered");
3042
+ return;
3043
+ }
3044
+ logger.info(`🔌 Loaded plugins (${plugins.length}):`);
3045
+ plugins.forEach((plugin) => {
3046
+ logger.info(` 📦 ${plugin.name} v${plugin.version} - ${plugin.description}`);
3047
+ logger.info(` Commands: ${plugin.commands.map((c) => c.name).join(", ")}`);
3048
+ });
3049
+ }
3050
+ }
3051
+ function createDefaultCLI() {
3052
+ const processor = new CommandProcessor();
3053
+ processor.registerCommand(new HelpCommand());
3054
+ processor.registerCommand(new ConfigCommand());
3055
+ processor.registerCommand(new ThemesCommand());
3056
+ processor.registerCommand(new BannersCommand());
3057
+ processor.registerCommand(new BannerCommand());
3058
+ processor.registerCommand(new StatusCommand());
3059
+ processor.registerCommand(new ResetCommand());
3060
+ processor.registerCommand(new DemoCommand());
3061
+ processor.registerCommand(new ExportCommand());
3062
+ processor.registerCommand(new CopyCommand());
3063
+ processor.registerCommand(new BufferSizeCommand());
3064
+ processor.registerCommand(new ClearBufferCommand());
3065
+ processor.registerCommand(new BufferInfoCommand());
3066
+ processor.registerCommand(new HistoryCommand());
3067
+ processor.registerCommand(new ClearHistoryCommand());
3068
+ processor.registerCommand(new InteractiveCommand());
3069
+ processor.registerCommand(new PluginsCommand());
3070
+ return processor;
3071
+ }
3072
+ let LEVEL_STYLES = THEME_PRESETS.default;
3073
+ class Logger {
3074
+ config;
3075
+ scopedPrefix;
3076
+ handlers = [];
3077
+ timers = /* @__PURE__ */ new Map();
3078
+ groupDepth = 0;
3079
+ exportHandler;
3080
+ cliProcessor;
3081
+ themeChangeListener;
3082
+ badgeList = [];
3083
+ displaySettings = {
3084
+ showTimestamp: true,
3085
+ showLocation: true,
3086
+ showBadges: true
3087
+ };
3088
+ serializerRegistry;
3089
+ hookManager;
3090
+ transportManager;
3091
+ /** Whether CLI primitives (step, box, header, etc.) should be shown @since 5.0.0 */
3092
+ _showPrimitives = true;
3093
+ /** Server-mode fallback for non-TTY environments @since 5.0.0 */
3094
+ _serverFallback;
3095
+ /**
3096
+ * Crea una nueva instancia del Logger
3097
+ *
3098
+ * @param {Partial<LoggerConfig>} config - Configuración opcional del logger
3099
+ *
3100
+ * @example
3101
+ * // Logger con configuración personalizada
3102
+ * const logger = new Logger({
3103
+ * theme: 'neon',
3104
+ * globalPrefix: 'MiApp',
3105
+ * verbosity: 'debug',
3106
+ * bufferSize: 1000
3107
+ * });
3108
+ */
3109
+ constructor(config = {}) {
3110
+ this.config = {
3111
+ ...DEFAULT_CONFIG$1,
3112
+ ...config
3113
+ };
3114
+ this.serializerRegistry = new SerializerRegistry();
3115
+ this.hookManager = new HookManager();
3116
+ if (this.config.bufferSize) {
3117
+ this.exportHandler = new ExportLogHandler(this.config.bufferSize);
3118
+ this.handlers.push(this.exportHandler);
3119
+ }
3120
+ this.cliProcessor = createDefaultCLI();
3121
+ if (this.config.autoDetectTheme) {
3122
+ this.setupAutoThemeDetection();
3123
+ }
3124
+ }
3125
+ // ===== PRIVATE HELPER METHODS =====
3126
+ /**
3127
+ * Configura la detección automática de tema con listener de cambios
3128
+ * @private
3129
+ * @description Detecta automáticamente si el navegador está en modo claro u oscuro
3130
+ */
3131
+ setupAutoThemeDetection() {
3132
+ if (this.themeChangeListener) {
3133
+ this.themeChangeListener();
3134
+ this.themeChangeListener = null;
3135
+ }
3136
+ this.themeChangeListener = setupThemeChangeListener((theme) => {
3137
+ this.debug(`DevTools theme changed to: ${theme}`);
3138
+ });
3139
+ }
3140
+ // ===== CONFIGURATION METHODS =====
3141
+ /**
3142
+ * Obtiene la configuración actual del logger
3143
+ *
3144
+ * @returns {LoggerConfig} Configuración completa actual
3145
+ *
3146
+ * @example
3147
+ * const config = logger.getConfig();
3148
+ * console.log('Verbosidad actual:', config.verbosity);
3149
+ * console.log('Tema actual:', config.theme);
3150
+ *
3151
+ * @since 0.3.0
3152
+ */
3153
+ getConfig() {
3154
+ return { ...this.config };
3155
+ }
3156
+ /**
3157
+ * Actualiza la configuración del logger
3158
+ *
3159
+ * @param {Partial<LoggerConfig>} updates - Propiedades a actualizar
3160
+ *
3161
+ * @example
3162
+ * logger.updateConfig({
3163
+ * verbosity: 'debug',
3164
+ * enableTimestamps: false,
3165
+ * theme: 'cyberpunk'
3166
+ * });
3167
+ *
3168
+ * @since 0.3.0
3169
+ */
3170
+ updateConfig(updates) {
3171
+ const previousAutoDetect = this.config.autoDetectTheme;
3172
+ this.config = { ...this.config, ...updates };
3173
+ if (updates.autoDetectTheme !== void 0 && updates.autoDetectTheme !== previousAutoDetect) {
3174
+ if (updates.autoDetectTheme) {
3175
+ this.setupAutoThemeDetection();
3176
+ } else if (this.themeChangeListener) {
3177
+ this.themeChangeListener();
3178
+ this.themeChangeListener = null;
3179
+ }
3180
+ }
3181
+ }
3182
+ /**
3183
+ * Establece el prefijo global para todos los mensajes de log
3184
+ *
3185
+ * @param {string} prefix - Prefijo a usar
3186
+ *
3187
+ * @example
3188
+ * logger.setGlobalPrefix('MiApp');
3189
+ * logger.info('Iniciado'); // [MiApp] Iniciado
3190
+ *
3191
+ * @since 0.3.0
3192
+ */
3193
+ setGlobalPrefix(prefix) {
3194
+ this.config.globalPrefix = prefix;
3195
+ }
3196
+ /**
3197
+ * Establece el nivel de verbosidad para filtrar la salida de logs
3198
+ *
3199
+ * @param {Verbosity} level - Nivel mínimo a mostrar ('debug' | 'info' | 'warn' | 'error' | 'critical' | 'silent')
3200
+ *
3201
+ * @example
3202
+ * logger.setVerbosity('warn'); // Solo muestra warn, error y critical
3203
+ * logger.setVerbosity('debug'); // Muestra todos los niveles
3204
+ * logger.setVerbosity('silent'); // No muestra nada
3205
+ *
3206
+ * @since 0.3.0
3207
+ */
3208
+ setVerbosity(level) {
3209
+ this.config.verbosity = level;
3210
+ }
3211
+ /**
3212
+ * Establece el tema del logger
3213
+ *
3214
+ * @param {ThemeVariant} theme - Tema a aplicar ('default' | 'dark' | 'light' | 'neon' | 'minimal' | 'cyberpunk')
3215
+ *
3216
+ * @example
3217
+ * logger.setTheme('neon'); // Tema con colores neón
3218
+ * logger.setTheme('minimal'); // Tema minimalista
3219
+ * logger.setTheme('cyberpunk'); // Tema cyberpunk con efectos
3220
+ *
3221
+ * @since 0.3.0
3222
+ */
3223
+ setTheme(theme) {
3224
+ if (hasPreset(theme)) {
3225
+ this.preset(theme);
3226
+ return;
3227
+ }
3228
+ if (theme in THEME_PRESETS) {
3229
+ LEVEL_STYLES = THEME_PRESETS[theme];
3230
+ this.config.theme = theme;
3231
+ if (theme in THEME_BANNERS) {
3232
+ const themeBanner = THEME_BANNERS[theme];
3233
+ console.log(`%c${themeBanner.simple}`, themeBanner.style);
3234
+ }
3235
+ this.success(`Theme changed to: ${theme}`);
3236
+ } else {
3237
+ this.error(`Invalid theme: ${theme}. Available:`, [...getAvailablePresets(), ...Object.keys(THEME_PRESETS)]);
3238
+ }
3239
+ }
3240
+ /**
3241
+ * Establece el tipo de banner para mostrar en la inicialización
3242
+ *
3243
+ * @param {BannerType} bannerType - Tipo de banner ('simple' | 'ascii' | 'unicode' | 'svg' | 'animated')
3244
+ *
3245
+ * @example
3246
+ * logger.setBannerType('ascii'); // Banner con arte ASCII
3247
+ * logger.setBannerType('unicode'); // Banner con caracteres Unicode
3248
+ * logger.setBannerType('animated'); // Banner con animación
3249
+ *
3250
+ * @since 0.3.0
3251
+ */
3252
+ setBannerType(bannerType) {
3253
+ this.config.bannerType = bannerType;
3254
+ this.success(`Banner type changed to: ${bannerType}`);
3255
+ }
3256
+ /**
3257
+ * Reinicia el logger a la configuración por defecto
3258
+ *
3259
+ * @example
3260
+ * logger.resetConfig();
3261
+ * // Todo vuelve a la configuración inicial
3262
+ *
3263
+ * @since 0.3.0
3264
+ */
3265
+ resetConfig() {
3266
+ if (this.themeChangeListener) {
3267
+ this.themeChangeListener();
3268
+ this.themeChangeListener = null;
3269
+ }
3270
+ this.config = { ...DEFAULT_CONFIG$1 };
3271
+ LEVEL_STYLES = THEME_PRESETS.default;
3272
+ if (this.config.autoDetectTheme) {
3273
+ this.setupAutoThemeDetection();
3274
+ }
3275
+ this.success("Logger configuration reset to defaults");
3276
+ }
3277
+ /**
3278
+ * Método de limpieza para eliminar listeners y liberar recursos
3279
+ *
3280
+ * @example
3281
+ * // Antes de cerrar la aplicación
3282
+ * logger.cleanup();
3283
+ *
3284
+ * @since 0.3.0
3285
+ */
3286
+ cleanup() {
3287
+ if (this.themeChangeListener) {
3288
+ this.themeChangeListener();
3289
+ this.themeChangeListener = null;
3290
+ }
3291
+ this.transportManager?.close().catch(() => {
3292
+ });
3293
+ }
3294
+ // ===== SIMPLIFIED API =====
3295
+ /**
3296
+ * Aplica un preset inteligente - funciona perfectamente sin configuración
3297
+ *
3298
+ * @param {string} name - Nombre del preset a aplicar
3299
+ *
3300
+ * @example
3301
+ * // Presets disponibles
3302
+ * logger.preset('default'); // Limpio y adaptativo
3303
+ * logger.preset('cyberpunk'); // Colores neón, efectos brillantes
3304
+ * logger.preset('glassmorphism'); // Efectos de blur modernos
3305
+ * logger.preset('minimal'); // Minimalista y elegante
3306
+ * logger.preset('debug'); // Modo desarrollo detallado
3307
+ * logger.preset('production'); // Optimizado para producción
3308
+ *
3309
+ * @since 0.3.0
3310
+ */
3311
+ preset(name) {
3312
+ if (!hasPreset(name)) {
3313
+ this.error(`Unknown preset: ${name}. Available presets:`, getAvailablePresets());
3314
+ return;
3315
+ }
3316
+ const presetConfig = getSmartPreset(name);
3317
+ if (presetConfig) {
3318
+ this.displaySettings.showTimestamp = presetConfig.timestamp?.show ?? true;
3319
+ this.displaySettings.showLocation = presetConfig.location?.show ?? true;
3320
+ this._activePreset = presetConfig;
3321
+ this._activePresetName = name;
3322
+ if (getEnvironment() === "browser") {
3323
+ this.success(`Applied preset: ${name}`);
3324
+ }
3325
+ }
3326
+ }
3327
+ /**
3328
+ * Lista todos los presets disponibles
3329
+ *
3330
+ * @returns {string[]} Array con nombres de presets disponibles
3331
+ *
3332
+ * @example
3333
+ * const disponibles = logger.presets();
3334
+ * console.log(disponibles); // ['default', 'cyberpunk', 'glassmorphism', ...]
3335
+ *
3336
+ * @since 0.3.0
3337
+ */
3338
+ presets() {
3339
+ return getAvailablePresets();
3340
+ }
3341
+ // ===== TOGGLE METHODS =====
3342
+ /**
3343
+ * Oculta el timestamp en los logs
3344
+ *
3345
+ * @example
3346
+ * logger.hideTimestamp();
3347
+ * logger.info('Sin marca de tiempo'); // Sin timestamp visible
3348
+ *
3349
+ * @since 0.3.0
3350
+ */
3351
+ hideTimestamp() {
3352
+ this.displaySettings.showTimestamp = false;
3353
+ return this;
3354
+ }
3355
+ /**
3356
+ * Muestra el timestamp en los logs
3357
+ *
3358
+ * @example
3359
+ * logger.showTimestamp();
3360
+ * logger.info('Con marca de tiempo'); // [2024-01-15 10:30:45] Con marca de tiempo
3361
+ *
3362
+ * @since 0.3.0
3363
+ */
3364
+ showTimestamp() {
3365
+ this.displaySettings.showTimestamp = true;
3366
+ return this;
3367
+ }
3368
+ /**
3369
+ * Oculta la información de ubicación (archivo:línea) en los logs
3370
+ *
3371
+ * @example
3372
+ * logger.hideLocation();
3373
+ * logger.debug('Sin ubicación'); // Sin mostrar archivo:línea
3374
+ *
3375
+ * @since 0.3.0
3376
+ */
3377
+ hideLocation() {
3378
+ this.displaySettings.showLocation = false;
3379
+ return this;
3380
+ }
3381
+ /**
3382
+ * Muestra la información de ubicación (archivo:línea) en los logs
3383
+ *
3384
+ * @example
3385
+ * logger.showLocation();
3386
+ * logger.debug('Con ubicación'); // app.js:42 Con ubicación
3387
+ *
3388
+ * @since 0.3.0
3389
+ */
3390
+ showLocation() {
3391
+ this.displaySettings.showLocation = true;
3392
+ return this;
3393
+ }
3394
+ /**
3395
+ * Oculta los badges en los logs
3396
+ *
3397
+ * @example
3398
+ * logger.hideBadges();
3399
+ * const api = logger.api('REST');
3400
+ * api.info('Sin badges'); // Sin mostrar [API] [REST]
3401
+ *
3402
+ * @since 0.3.0
3403
+ */
3404
+ hideBadges() {
3405
+ this.displaySettings.showBadges = false;
3406
+ return this;
3407
+ }
3408
+ /**
3409
+ * Muestra los badges en los logs
3410
+ *
3411
+ * @example
3412
+ * logger.showBadges();
3413
+ * const api = logger.api('GraphQL');
3414
+ * api.info('Con badges'); // [API] [GraphQL] Con badges
3415
+ *
3416
+ * @since 0.3.0
3417
+ */
3418
+ showBadges() {
3419
+ this.displaySettings.showBadges = true;
3420
+ return this;
3421
+ }
3422
+ /**
3423
+ * Establece múltiples badges para los logs
3424
+ *
3425
+ * @param {string[]} badges - Array de badges a mostrar
3426
+ * @returns {this} Logger instance para encadenamiento
3427
+ *
3428
+ * @example
3429
+ * logger.badges(['v3', 'stable']).info('Release publicado');
3430
+ * logger.badges(['API', 'v2']).warn('Endpoint deprecado');
3431
+ *
3432
+ * @since 3.0.0
3433
+ */
3434
+ badges(badges2) {
3435
+ this.badgeList = [...badges2];
3436
+ return this;
3437
+ }
3438
+ /**
3439
+ * Añade un badge individual a la lista
3440
+ *
3441
+ * @param {string} badge - Badge a añadir
3442
+ * @returns {this} Logger instance para encadenamiento
3443
+ *
3444
+ * @example
3445
+ * logger.badge('DEBUG').badge('AUTH').info('Token validado');
3446
+ *
3447
+ * @since 3.0.0
3448
+ */
3449
+ badge(badge2) {
3450
+ if (!this.badgeList.includes(badge2)) {
3451
+ this.badgeList.push(badge2);
3452
+ }
3453
+ return this;
3454
+ }
3455
+ /**
3456
+ * Limpia todos los badges activos
3457
+ *
3458
+ * @returns {this} Logger instance para encadenamiento
3459
+ *
3460
+ * @example
3461
+ * logger.clearBadges().info('Sin badges');
3462
+ *
3463
+ * @since 3.0.0
3464
+ */
3465
+ clearBadges() {
3466
+ this.badgeList = [];
3467
+ return this;
3468
+ }
3469
+ // ===== SCOPED LOGGERS =====
3470
+ component(name) {
3471
+ return new ComponentLogger(this, name);
3472
+ }
3473
+ api(name) {
3474
+ return new APILogger(this, name);
3475
+ }
3476
+ scope(name) {
3477
+ return new ScopedLogger(this, name);
3478
+ }
3479
+ // ===== SIMPLE CUSTOMIZATION =====
3480
+ /**
3481
+ * Personalización simple con configuración mínima
3482
+ *
3483
+ * @param {Object} overrides - Opciones de personalización
3484
+ * @param {Object} overrides.message - Configuración del mensaje
3485
+ * @param {Object} overrides.timestamp - Configuración del timestamp
3486
+ * @param {Object} overrides.location - Configuración de ubicación
3487
+ * @param {Object} overrides.level - Configuración del nivel
3488
+ * @param {Object} overrides.prefix - Configuración del prefijo
3489
+ * @param {string} overrides.spacing - Espaciado: 'compact' | 'normal' | 'spacious'
3490
+ *
3491
+ * @example
3492
+ * logger.customize({
3493
+ * message: { color: '#00ff00', size: '16px' },
3494
+ * timestamp: { show: false },
3495
+ * spacing: 'compact'
3496
+ * });
3497
+ *
3498
+ * @since 0.3.0
3499
+ */
3500
+ customize(overrides) {
3501
+ if (overrides.timestamp?.show !== void 0) {
3502
+ this.displaySettings.showTimestamp = overrides.timestamp.show;
3503
+ }
3504
+ if (overrides.location?.show !== void 0) {
3505
+ this.displaySettings.showLocation = overrides.location.show;
3506
+ }
3507
+ if (overrides.prefix?.show !== void 0) ;
3508
+ this._customization = overrides;
3509
+ this.success("Customization applied");
3510
+ }
3511
+ /**
3512
+ * Access advanced styling API (for power users)
3513
+ */
3514
+ styles() {
3515
+ return createLogStyleBuilder(this);
3516
+ }
3517
+ // ===== HANDLER MANAGEMENT =====
3518
+ /**
3519
+ * Añade un handler personalizado para extender funcionalidad
3520
+ *
3521
+ * @param {ILogHandler} handler - Handler que implementa ILogHandler
3522
+ *
3523
+ * @example
3524
+ * // Handler personalizado para enviar logs a servidor
3525
+ * const remoteHandler = new RemoteLogHandler('https://api.ejemplo.com/logs');
3526
+ * logger.addHandler(remoteHandler);
3527
+ *
3528
+ * @example
3529
+ * // Handler para guardar en archivo
3530
+ * const fileHandler = new FileLogHandler('./app.log');
3531
+ * logger.addHandler(fileHandler);
3532
+ *
3533
+ * @since 0.3.0
3534
+ */
3535
+ addHandler(handler) {
3536
+ this.handlers.push(handler);
3537
+ }
3538
+ /**
3539
+ * Obtiene todos los handlers registrados
3540
+ *
3541
+ * @returns {ILogHandler[]} Array de handlers activos
3542
+ * @since 0.3.0
3543
+ */
3544
+ getHandlers() {
3545
+ return [...this.handlers];
3546
+ }
3547
+ /**
3548
+ * Obtiene el handler de exportación si está disponible
3549
+ *
3550
+ * @returns {ExportLogHandler | undefined} Handler de exportación o undefined
3551
+ * @since 0.3.0
3552
+ */
3553
+ getExportHandler() {
3554
+ return this.exportHandler;
3555
+ }
3556
+ // ===== SERIALIZERS =====
3557
+ /**
3558
+ * Añade un serializador personalizado para un tipo específico
3559
+ *
3560
+ * @param type - Constructor del tipo a serializar
3561
+ * @param serializer - Función de serialización
3562
+ * @param priority - Prioridad (mayor = primero)
3563
+ *
3564
+ * @example
3565
+ * logger.addSerializer(Error, (err) => ({
3566
+ * name: err.name,
3567
+ * message: err.message,
3568
+ * stack: err.stack?.split('\n').slice(0, 5)
3569
+ * }));
3570
+ *
3571
+ * @since 3.0.0
3572
+ */
3573
+ addSerializer(type, serializer, priority) {
3574
+ this.serializerRegistry.add(type, serializer, priority);
3575
+ }
3576
+ /**
3577
+ * Elimina un serializador registrado
3578
+ *
3579
+ * @param type - Constructor del tipo a remover
3580
+ * @returns true si se eliminó
3581
+ *
3582
+ * @since 3.0.0
3583
+ */
3584
+ removeSerializer(type) {
3585
+ return this.serializerRegistry.remove(type);
3586
+ }
3587
+ /**
3588
+ * Obtiene el registry de serializadores
3589
+ *
3590
+ * @returns SerializerRegistry
3591
+ * @since 3.0.0
3592
+ */
3593
+ getSerializerRegistry() {
3594
+ return this.serializerRegistry;
3595
+ }
3596
+ // ===== HOOKS & MIDDLEWARE =====
3597
+ /**
3598
+ * Registra un hook para un evento
3599
+ *
3600
+ * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
3601
+ * @param callback - Función a ejecutar
3602
+ * @param priority - Prioridad (mayor = primero)
3603
+ * @returns Función para desregistrar
3604
+ *
3605
+ * @example
3606
+ * const unsubscribe = logger.on('beforeLog', (entry) => {
3607
+ * entry.correlationId = getCorrelationId();
3608
+ * return entry;
3609
+ * });
3610
+ *
3611
+ * @since 3.0.0
3612
+ */
3613
+ on(event, callback, priority) {
3614
+ return this.hookManager.on(event, callback, priority);
3615
+ }
3616
+ /**
3617
+ * Registra un hook que se ejecuta solo una vez
3618
+ *
3619
+ * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
3620
+ * @param callback - Función a ejecutar
3621
+ * @param priority - Prioridad (mayor = primero)
3622
+ * @returns Función para desregistrar
3623
+ *
3624
+ * @since 3.0.0
3625
+ */
3626
+ once(event, callback, priority) {
3627
+ return this.hookManager.once(event, callback, priority);
3628
+ }
3629
+ /**
3630
+ * Elimina un hook registrado
3631
+ *
3632
+ * @param event - Evento del hook
3633
+ * @param callback - Callback a remover
3634
+ * @returns true si se eliminó
3635
+ *
3636
+ * @since 3.0.0
3637
+ */
3638
+ off(event, callback) {
3639
+ return this.hookManager.off(event, callback);
3640
+ }
3641
+ /**
3642
+ * Añade un middleware al pipeline
3643
+ *
3644
+ * @param middleware - Función middleware
3645
+ * @param priority - Prioridad (mayor = primero)
3646
+ * @returns Función para desregistrar
3647
+ *
3648
+ * @example
3649
+ * logger.use((entry, next) => {
3650
+ * entry.requestId = asyncLocalStorage.getStore()?.requestId;
3651
+ * next();
3652
+ * });
3653
+ *
3654
+ * @since 3.0.0
3655
+ */
3656
+ use(middleware, priority) {
3657
+ return this.hookManager.use(middleware, priority);
3658
+ }
3659
+ /**
3660
+ * Obtiene el HookManager
3661
+ *
3662
+ * @returns HookManager
3663
+ * @since 3.0.0
3664
+ */
3665
+ getHookManager() {
3666
+ return this.hookManager;
3667
+ }
3668
+ // ===== TRANSPORTS =====
3669
+ /**
3670
+ * Añade un transport para envío de logs
3671
+ *
3672
+ * @param target - Configuración del transport
3673
+ * @returns ID único del transport
3674
+ *
3675
+ * @example
3676
+ * // File transport
3677
+ * logger.addTransport({
3678
+ * target: 'file',
3679
+ * options: { destination: '/var/log/app.log' }
3680
+ * });
3681
+ *
3682
+ * @example
3683
+ * // HTTP transport con batching
3684
+ * logger.addTransport({
3685
+ * target: 'http',
3686
+ * options: {
3687
+ * url: 'https://logs.example.com',
3688
+ * batchSize: 100,
3689
+ * flushInterval: 5000
3690
+ * },
3691
+ * level: 'warn'
3692
+ * });
3693
+ *
3694
+ * @since 3.0.0
3695
+ */
3696
+ addTransport(target) {
3697
+ if (!this.transportManager) {
3698
+ this.transportManager = new TransportManager();
3699
+ }
3700
+ return this.transportManager.add(target);
3701
+ }
3702
+ /**
3703
+ * Elimina un transport
3704
+ *
3705
+ * @param id - ID del transport a remover
3706
+ * @returns true si se eliminó
3707
+ *
3708
+ * @since 3.0.0
3709
+ */
3710
+ removeTransport(id) {
3711
+ return this.transportManager?.remove(id) ?? false;
3712
+ }
3713
+ /**
3714
+ * Fuerza el flush de todos los transports
3715
+ *
3716
+ * @returns Promise que resuelve cuando todos los buffers están vaciados
3717
+ *
3718
+ * @since 3.0.0
3719
+ */
3720
+ async flushTransports() {
3721
+ await this.transportManager?.flush();
3722
+ }
3723
+ /**
3724
+ * Cierra todos los transports
3725
+ *
3726
+ * @returns Promise que resuelve cuando todos están cerrados
3727
+ *
3728
+ * @since 3.0.0
3729
+ */
3730
+ async closeTransports() {
3731
+ await this.transportManager?.close();
3732
+ }
3733
+ /**
3734
+ * Obtiene el TransportManager
3735
+ *
3736
+ * @returns TransportManager o undefined si no hay transports
3737
+ * @since 3.0.0
3738
+ */
3739
+ getTransportManager() {
3740
+ return this.transportManager;
3741
+ }
3742
+ // ===== CORE LOGGING METHODS =====
3743
+ /**
3744
+ * Verifica si un nivel de log debe mostrarse según la verbosidad actual
3745
+ * @private
3746
+ * @param {LogLevel} level - Nivel de log a verificar
3747
+ * @returns {boolean} True si debe mostrarse, false si no
3748
+ */
3749
+ shouldLog(level) {
3750
+ if (this.config.verbosity === "silent") return false;
3751
+ const levels = { debug: 0, info: 1, warn: 2, error: 3, critical: 4 };
3752
+ return levels[level] >= levels[this.config.verbosity];
3753
+ }
3754
+ /**
3755
+ * Obtiene el prefijo efectivo (global + scope)
3756
+ * @private
3757
+ * @returns {string | undefined} Prefijo combinado o undefined
3758
+ */
3759
+ getEffectivePrefix() {
3760
+ const parts = [this.config.globalPrefix, this.scopedPrefix].filter(Boolean);
3761
+ return parts.length > 0 ? parts.join(":") : void 0;
3762
+ }
3763
+ /**
3764
+ * Método central de logging que maneja estilos y formato
3765
+ * @protected
3766
+ * @param {LogLevel} level - Nivel del log
3767
+ * @param {...any} args - Argumentos a loggear
3768
+ */
3769
+ log(level, ...args) {
3770
+ if (!this.shouldLog(level)) return;
3771
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
3772
+ const prefix = this.getEffectivePrefix();
3773
+ const timestamp = formatTimestamp();
3774
+ const serializedArgs = args.map((arg) => this.serializerRegistry.serialize(arg));
3775
+ let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : "";
3776
+ if (this.badgeList.length > 0 && this.displaySettings.showBadges) {
3777
+ const badgePrefix = this.badgeList.map((b) => `[${b}]`).join("");
3778
+ message = badgePrefix + " " + message;
3779
+ }
3780
+ const additionalArgs = serializedArgs.slice(1);
3781
+ let hookEntry = {
3782
+ level,
3783
+ message,
3784
+ args: serializedArgs,
3785
+ timestamp,
3786
+ prefix,
3787
+ stackInfo: stackInfo || void 0
3788
+ };
3789
+ this.hookManager.emit("beforeLog", hookEntry).then((processed) => {
3790
+ message = processed.message;
3791
+ }).catch(() => {
3792
+ });
3793
+ const [format, ...styles2] = createStyledOutput(
3794
+ level,
3795
+ LEVEL_STYLES,
3796
+ prefix,
3797
+ message,
3798
+ this.displaySettings.showLocation ? stackInfo : null,
3799
+ this.config.autoDetectTheme,
3800
+ this._activePreset,
3801
+ this._activePresetName
3802
+ );
3803
+ const groupIndent = " ".repeat(this.groupDepth);
3804
+ const finalFormat = groupIndent + format;
3805
+ this.writeOutput(finalFormat, level, styles2, additionalArgs);
3806
+ if (this.exportHandler) {
3807
+ this.exportHandler.setGroupInfo(this.groupDepth);
3808
+ }
3809
+ const metadata = {
3810
+ timestamp,
3811
+ level,
3812
+ prefix,
3813
+ stackInfo: stackInfo ? stackInfo : void 0
3814
+ };
3815
+ this.handlers.forEach((handler) => {
3816
+ try {
3817
+ handler.handle(level, message, serializedArgs, metadata);
3818
+ } catch (error2) {
3819
+ console.error("Log handler failed:", error2);
3820
+ }
3821
+ });
3822
+ if (this.transportManager) {
3823
+ const levelValues = {
3824
+ debug: 0,
3825
+ info: 1,
3826
+ warn: 2,
3827
+ error: 3,
3828
+ critical: 4
3829
+ };
3830
+ const record = {
3831
+ level,
3832
+ levelValue: levelValues[level],
3833
+ time: Date.now(),
3834
+ msg: message,
3835
+ prefix,
3836
+ location: stackInfo ? {
3837
+ file: stackInfo.file,
3838
+ line: stackInfo.line,
3839
+ column: stackInfo.column,
3840
+ function: stackInfo.function
3841
+ } : void 0
3842
+ };
3843
+ this.transportManager.write(record).catch(() => {
3844
+ });
3845
+ }
3846
+ this.hookManager.emit("afterLog", hookEntry).catch(() => {
3847
+ });
3848
+ }
3849
+ logWithBindings(bindings, level, ...args) {
3850
+ if (!this.shouldLog(level)) return;
3851
+ let prefix = "";
3852
+ const colorCapability = getColorCapability();
3853
+ if (bindings.badges?.length) {
3854
+ prefix += bindings.badges.map((b) => formatBadge(b, "pill", colorCapability, "#00ff88")).join(" ") + " ";
3855
+ }
3856
+ if (bindings.scope) {
3857
+ prefix += formatBadge(bindings.scope, "pill", colorCapability, "#00ffff") + " ";
3858
+ }
3859
+ if (prefix && args.length > 0) {
3860
+ args[0] = prefix + String(args[0]);
3861
+ }
3862
+ this.log(level, ...args);
3863
+ }
3864
+ debug(...args) {
3865
+ this.log("debug", ...args);
3866
+ }
3867
+ /**
3868
+ * Registra mensajes informativos
3869
+ *
3870
+ * @param {...any} args - Mensajes y datos informativos
3871
+ *
3872
+ * @example
3873
+ * logger.info('Servidor iniciado en puerto 3000');
3874
+ * logger.info('Usuario conectado:', userId);
3875
+ * logger.info('Procesando', totalItems, 'elementos');
3876
+ *
3877
+ * @since 0.3.0
3878
+ */
3879
+ info(...args) {
3880
+ this.log("info", ...args);
3881
+ }
3882
+ /**
3883
+ * Registra mensajes de advertencia
3884
+ *
3885
+ * @param {...any} args - Mensajes de advertencia
3886
+ *
3887
+ * @example
3888
+ * logger.warn('Memoria al 85% de capacidad');
3889
+ * logger.warn('API deprecada, usar v2');
3890
+ * logger.warn('Reintentos agotados:', maxRetries);
3891
+ *
3892
+ * @since 0.3.0
3893
+ */
3894
+ warn(...args) {
3895
+ this.log("warn", ...args);
3896
+ }
3897
+ /**
3898
+ * Registra mensajes de error
3899
+ *
3900
+ * @param {...any} args - Mensajes de error y stack traces
3901
+ *
3902
+ * @example
3903
+ * logger.error('Fallo en conexión a base de datos');
3904
+ * logger.error('Error al procesar:', error.message, error.stack);
3905
+ * logger.error('Código de error:', errorCode);
3906
+ *
3907
+ * @since 0.3.0
3908
+ */
3909
+ error(...args) {
3910
+ this.log("error", ...args);
3911
+ }
3912
+ /**
3913
+ * Registra mensajes de éxito (nivel info especial)
3914
+ *
3915
+ * @param {...any} args - Mensajes de operaciones exitosas
3916
+ *
3917
+ * @example
3918
+ * logger.success('Base de datos conectada');
3919
+ * logger.success('Usuario creado con ID:', userId);
3920
+ * logger.success('✓ Tests pasados: 42/42');
3921
+ *
3922
+ * @since 0.3.0
3923
+ */
3924
+ success(...args) {
3925
+ if (!this.shouldLog("info")) return;
3926
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
3927
+ const prefix = this.getEffectivePrefix();
3928
+ const message = args.length > 0 ? String(args[0]) : "";
3929
+ const additionalArgs = args.slice(1);
3930
+ const [format, ...styles2] = createStyledOutput(
3931
+ "info",
3932
+ LEVEL_STYLES,
3933
+ prefix,
3934
+ message,
3935
+ this.displaySettings.showLocation ? stackInfo : null,
3936
+ this.config.autoDetectTheme,
3937
+ this._activePreset,
3938
+ this._activePresetName
3939
+ );
3940
+ const successStyle = LEVEL_STYLES.success;
3941
+ let emoji = "✅";
3942
+ let label = "SUCCESS";
3943
+ if (successStyle) {
3944
+ if (successStyle.emoji) {
3945
+ emoji = successStyle.emoji;
3946
+ }
3947
+ if (successStyle.label) {
3948
+ label = successStyle.label;
3949
+ }
3950
+ }
3951
+ const successFormat = format.replace(/ℹ️ INFO/, `${emoji} ${label}`);
3952
+ const groupIndent = " ".repeat(this.groupDepth);
3953
+ const finalFormat = groupIndent + successFormat;
3954
+ if (additionalArgs.length > 0) {
3955
+ console.log(finalFormat, ...styles2, ...additionalArgs);
3956
+ } else {
3957
+ console.log(finalFormat, ...styles2);
3958
+ }
3959
+ const metadata = {
3960
+ timestamp: formatTimestamp(),
3961
+ level: "info",
3962
+ prefix,
3963
+ stackInfo: stackInfo ? stackInfo : void 0
3964
+ };
3965
+ this.handlers.forEach((handler) => {
3966
+ try {
3967
+ handler.handle("info", message, args, metadata);
3968
+ } catch (error2) {
3969
+ console.error("Log handler failed:", error2);
3970
+ }
3971
+ });
3972
+ }
3973
+ /**
3974
+ * Registra información de trace (debugging detallado)
3975
+ *
3976
+ * @param {...any} args - Datos detallados para debugging
3977
+ *
3978
+ * @example
3979
+ * logger.trace('Entrando en función processData');
3980
+ * logger.trace('Stack completo:', new Error().stack);
3981
+ *
3982
+ * @since 0.3.0
3983
+ */
3984
+ trace(...args) {
3985
+ this.log("debug", ...args);
3986
+ if (this.shouldLog("debug")) {
3987
+ console.trace(...args);
3988
+ }
3989
+ }
3990
+ /**
3991
+ * Registra errores críticos (prioridad más alta)
3992
+ *
3993
+ * @param {...any} args - Errores críticos del sistema
3994
+ *
3995
+ * @example
3996
+ * logger.critical('Sistema caído - reinicio inmediato requerido');
3997
+ * logger.critical('Pérdida de datos detectada');
3998
+ * logger.critical('Brecha de seguridad:', securityError);
3999
+ *
4000
+ * @since 0.3.0
4001
+ */
4002
+ critical(...args) {
4003
+ this.log("critical", ...args);
4004
+ }
4005
+ // ===== ADVANCED LOGGING FEATURES =====
4006
+ /**
4007
+ * Muestra datos en formato de tabla
4008
+ *
4009
+ * @param {any} data - Datos a mostrar (array de objetos o matriz)
4010
+ * @param {string[]} columns - Columnas específicas a mostrar (opcional)
4011
+ *
4012
+ * @example
4013
+ * const usuarios = [
4014
+ * { id: 1, nombre: 'Juan', edad: 30 },
4015
+ * { id: 2, nombre: 'María', edad: 25 }
4016
+ * ];
4017
+ * logger.table(usuarios);
4018
+ * logger.table(usuarios, ['nombre', 'edad']); // Solo estas columnas
4019
+ *
4020
+ * @since 0.3.0
4021
+ */
4022
+ table(data, columns) {
4023
+ if (!this.shouldLog("info")) return;
4024
+ const prefix = this.getEffectivePrefix();
4025
+ const tableStyle = StylePresets.accent().build();
4026
+ const format = `%c📊 TABLE${prefix ? ` [${prefix}]` : ""}`;
4027
+ console.log(format, tableStyle);
4028
+ if (columns) {
4029
+ console.table(data, columns);
4030
+ } else {
4031
+ console.table(data);
4032
+ }
4033
+ }
4034
+ /**
4035
+ * Inicia un grupo colapsable en la consola
4036
+ *
4037
+ * @param {string} label - Etiqueta del grupo
4038
+ * @param {boolean} collapsed - Si el grupo inicia colapsado (default: false)
4039
+ *
4040
+ * @example
4041
+ * logger.group('Procesando usuarios');
4042
+ * logger.info('Usuario 1 procesado');
4043
+ * logger.info('Usuario 2 procesado');
4044
+ * logger.groupEnd();
4045
+ *
4046
+ * @example
4047
+ * // Grupo colapsado por defecto
4048
+ * logger.group('Detalles adicionales', true);
4049
+ * logger.debug('Información detallada aquí');
4050
+ * logger.groupEnd();
4051
+ *
4052
+ * @since 0.3.0
4053
+ */
4054
+ group(label, collapsed = false) {
4055
+ const groupStyle = new StyleBuilder().bg("linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)").color("#1565c0").border("1px solid #90caf9").padding("4px 12px").rounded("6px").bold().build();
4056
+ const format = `%c📁 ${label}`;
4057
+ if (collapsed) {
4058
+ console.groupCollapsed(format, groupStyle);
4059
+ } else {
4060
+ console.group(format, groupStyle);
4061
+ }
4062
+ this.groupDepth++;
4063
+ }
4064
+ /**
4065
+ * Finaliza el grupo actual de la consola
4066
+ *
4067
+ * @example
4068
+ * logger.group('Operaciones');
4069
+ * logger.info('Operación 1');
4070
+ * logger.info('Operación 2');
4071
+ * logger.groupEnd(); // Cierra el grupo
4072
+ *
4073
+ * @since 0.3.0
4074
+ */
4075
+ groupEnd() {
4076
+ if (this.groupDepth > 0) {
4077
+ console.groupEnd();
4078
+ this.groupDepth--;
4079
+ }
4080
+ }
4081
+ // ===== PERFORMANCE TIMING =====
4082
+ /**
4083
+ * Inicia un temporizador con la etiqueta dada
4084
+ *
4085
+ * @param {string} label - Etiqueta identificadora del temporizador
4086
+ *
4087
+ * @example
4088
+ * logger.time('proceso-datos');
4089
+ * // ... operación costosa ...
4090
+ * logger.timeEnd('proceso-datos'); // ⏱️ Timer ended: proceso-datos - 1523.45ms
4091
+ *
4092
+ * @since 0.3.0
4093
+ */
4094
+ time(label) {
4095
+ const timer = {
4096
+ label,
4097
+ startTime: performance.now()
4098
+ };
4099
+ this.timers.set(label, timer);
4100
+ const timerStyle = StylePresets.warning().build();
4101
+ console.log(`%c⏱️ Timer started: ${label}`, timerStyle);
4102
+ }
4103
+ /**
4104
+ * Finaliza un temporizador y muestra el tiempo transcurrido
4105
+ *
4106
+ * @param {string} label - Etiqueta del temporizador a finalizar
4107
+ * @returns {number} Elapsed milliseconds, or -1 if timer not found
4108
+ *
4109
+ * @example
4110
+ * logger.time('consulta-db');
4111
+ * await consultarBaseDatos();
4112
+ * const elapsed = logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
4113
+ *
4114
+ * @since 0.3.0
4115
+ */
4116
+ timeEnd(label) {
4117
+ const timer = this.timers.get(label);
4118
+ if (!timer) {
4119
+ this.warn(`Timer '${label}' does not exist`);
4120
+ return -1;
4121
+ }
4122
+ const elapsed = performance.now() - timer.startTime;
4123
+ this.timers.delete(label);
4124
+ const timerStyle = StylePresets.success().build();
4125
+ console.log(`%c⏱️ Timer ended: ${label} - ${elapsed.toFixed(2)}ms`, timerStyle);
4126
+ return elapsed;
4127
+ }
4128
+ // ===== ADVANCED VISUAL FEATURES =====
4129
+ /**
4130
+ * Muestra un banner con el tipo especificado o configurado
4131
+ *
4132
+ * @param {BannerType} bannerType - Tipo de banner (opcional)
4133
+ *
4134
+ * @example
4135
+ * logger.showBanner('ascii'); // Banner ASCII art
4136
+ * logger.showBanner('unicode'); // Banner con caracteres Unicode
4137
+ * logger.showBanner('svg'); // Banner con gráfico SVG
4138
+ * logger.showBanner(); // Usa el tipo configurado
4139
+ *
4140
+ * @since 0.3.0
4141
+ */
4142
+ showBanner(bannerType) {
4143
+ const effectiveBannerType = bannerType ? bannerType : this.config.bannerType;
4144
+ displayInitBanner(effectiveBannerType);
4145
+ }
4146
+ /**
4147
+ * Registra mensaje con imagen SVG de fondo
4148
+ *
4149
+ * @param {string} message - Mensaje a mostrar
4150
+ * @param {string} svgContent - Contenido SVG personalizado (opcional)
4151
+ * @param {StyleOptions} options - Opciones de estilo (ancho, alto, padding)
4152
+ *
4153
+ * @example
4154
+ * // SVG automático con gradiente
4155
+ * logger.logWithSVG('🎆 Bienvenido a Better Logger');
4156
+ *
4157
+ * @example
4158
+ * // SVG personalizado
4159
+ * const customSVG = '<svg>...</svg>';
4160
+ * logger.logWithSVG('Logo', customSVG, { width: 400, height: 100 });
4161
+ *
4162
+ * @since 0.3.0
4163
+ */
4164
+ logWithSVG(message, svgContent, options = {}) {
4165
+ const { width = 300, height = 60, padding = "30px 150px" } = options;
4166
+ let svgDataUri = "";
4167
+ if (svgContent) {
4168
+ const encodedSVG = encodeURIComponent(svgContent);
4169
+ svgDataUri = `data:image/svg+xml,${encodedSVG}`;
4170
+ } else {
4171
+ const defaultSVG = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 ${width} ${height}'><defs><linearGradient id='grad' x1='0%' y1='0%' x2='100%' y2='0%'><stop offset='0%' style='stop-color:%23667eea'/><stop offset='100%' style='stop-color:%23764ba2'/></linearGradient></defs><rect width='100%' height='100%' fill='url(%23grad)' rx='4'/><text x='${width / 2}' y='${height / 2 + 5}' text-anchor='middle' fill='white' font-family='monospace' font-size='14' font-weight='bold'>${message}</text></svg>`;
4172
+ svgDataUri = `data:image/svg+xml,${encodeURIComponent(defaultSVG)}`;
4173
+ }
4174
+ const svgStyle = new StyleBuilder().bg(`url("${svgDataUri}") no-repeat center center`).padding(padding).color("transparent").rounded("4px").build();
4175
+ console.log(`%c${message}`, svgStyle);
4176
+ }
4177
+ /**
4178
+ * Registra mensaje con gradiente animado de fondo
4179
+ *
4180
+ * @param {string} message - Mensaje a animar
4181
+ * @param {number} duration - Duración de la animación en segundos (default: 3)
4182
+ *
4183
+ * @example
4184
+ * logger.logAnimated('🌈 Animación en progreso');
4185
+ * logger.logAnimated('Cargando...', 5); // Animación de 5 segundos
4186
+ *
4187
+ * @since 0.3.0
4188
+ */
4189
+ logAnimated(message, duration = 3) {
4190
+ if (!document.getElementById("logger-animations")) {
4191
+ const style = document.createElement("style");
4192
+ style.id = "logger-animations";
4193
+ style.textContent = `
4194
+ @keyframes loggerGradient {
4195
+ 0% { background-position: 0% 50%; }
4196
+ 50% { background-position: 100% 50%; }
4197
+ 100% { background-position: 0% 50%; }
4198
+ }
4199
+ `;
4200
+ document.head.appendChild(style);
4201
+ }
4202
+ const animatedStyle = new StyleBuilder().bg("linear-gradient(-45deg, #667eea, #764ba2, #667eea, #764ba2)").css("background-size", "400% 400%").color("#ffffff").padding("12px 20px").rounded("8px").bold().font("Monaco, Consolas, monospace").animation(`loggerGradient ${duration}s ease infinite`).display("inline-block").build();
4203
+ console.log(`%c${message}`, animatedStyle);
4204
+ }
4205
+ /**
4206
+ * Agrupa logs por una propiedad específica usando Object.groupBy (cuando esté disponible)
4207
+ *
4208
+ * @param {T[]} items - Array de elementos a agrupar
4209
+ * @param {Function} groupBy - Función que retorna la clave de agrupación
4210
+ *
4211
+ * @example
4212
+ * const ventas = [
4213
+ * { producto: 'Laptop', categoria: 'Electrónica', precio: 1200 },
4214
+ * { producto: 'Mouse', categoria: 'Electrónica', precio: 25 },
4215
+ * { producto: 'Libro', categoria: 'Literatura', precio: 15 }
4216
+ * ];
4217
+ * logger.logGrouped(ventas, item => item.categoria);
4218
+ *
4219
+ * @since 0.3.0
4220
+ */
4221
+ logGrouped(items, groupBy) {
4222
+ try {
4223
+ let grouped;
4224
+ if (Object.groupBy) {
4225
+ grouped = Object.groupBy(items, groupBy);
4226
+ } else {
4227
+ grouped = items.reduce((acc, item) => {
4228
+ const key = groupBy(item);
4229
+ if (!acc[key]) {
4230
+ acc[key] = [];
4231
+ }
4232
+ acc[key].push(item);
4233
+ return acc;
4234
+ }, {});
4235
+ }
4236
+ Object.entries(grouped).forEach(([group2, groupItems]) => {
4237
+ this.group(`Group: ${group2}`);
4238
+ this.table(groupItems);
4239
+ this.groupEnd();
4240
+ });
4241
+ } catch {
4242
+ this.info("Grouped data:", items);
4243
+ }
4244
+ }
4245
+ // ===== CLI PRIMITIVES (v5.0) =====
4246
+ /**
4247
+ * Displays a step progress indicator in the terminal
4248
+ *
4249
+ * @param {number} current - Current step number
4250
+ * @param {number} total - Total number of steps
4251
+ * @param {string} message - Step description
4252
+ *
4253
+ * @example
4254
+ * logger.step(1, 5, 'Analyzing repository...');
4255
+ * logger.step(2, 5, 'Generating commit message...');
4256
+ *
4257
+ * @since 5.0.0
4258
+ */
4259
+ step(current, total, message) {
4260
+ if (!this._showPrimitives) return;
4261
+ if (!isRunningInTerminal()) {
4262
+ this.getServerFallback().step(current, total, message);
4263
+ return;
4264
+ }
4265
+ const colorCap = getColorCapability();
4266
+ const output = renderStep(current, total, message, colorCap);
4267
+ process.stderr.write(output + "\n");
4268
+ }
4269
+ /**
4270
+ * Displays a styled header with optional subtitle
4271
+ *
4272
+ * @param {string} title - Main title text
4273
+ * @param {string} subtitle - Optional subtitle (rendered dimmed)
4274
+ *
4275
+ * @example
4276
+ * logger.header('Commit Wizard', 'v2.0.0');
4277
+ *
4278
+ * @since 5.0.0
4279
+ */
4280
+ header(title, subtitle) {
4281
+ if (!this._showPrimitives) return;
4282
+ if (!isRunningInTerminal()) {
4283
+ this.getServerFallback().header(title, subtitle);
4284
+ return;
4285
+ }
4286
+ const output = renderHeader(title, subtitle);
4287
+ process.stderr.write(output + "\n");
4288
+ }
4289
+ /**
4290
+ * Displays a horizontal divider line
4291
+ *
4292
+ * @example
4293
+ * logger.divider();
4294
+ *
4295
+ * @since 5.0.0
4296
+ */
4297
+ divider() {
4298
+ if (!this._showPrimitives) return;
4299
+ if (!isRunningInTerminal()) {
4300
+ this.getServerFallback().divider();
4301
+ return;
4302
+ }
4303
+ const output = renderDivider();
4304
+ process.stderr.write(output + "\n");
4305
+ }
4306
+ /**
4307
+ * Outputs a blank line
4308
+ *
4309
+ * @example
4310
+ * logger.blank();
4311
+ *
4312
+ * @since 5.0.0
4313
+ */
4314
+ blank() {
4315
+ if (!this._showPrimitives) return;
4316
+ if (!isRunningInTerminal()) {
4317
+ this.getServerFallback().blank();
4318
+ return;
4319
+ }
4320
+ process.stderr.write("\n");
4321
+ }
4322
+ /**
4323
+ * Renders content inside a bordered box
4324
+ *
4325
+ * @param {string} content - Content string (may contain newlines)
4326
+ * @param {IBoxOptions} options - Box rendering options
4327
+ *
4328
+ * @example
4329
+ * logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
4330
+ *
4331
+ * @since 5.0.0
4332
+ */
4333
+ box(content, options) {
4334
+ if (!this._showPrimitives) return;
4335
+ if (!isRunningInTerminal()) {
4336
+ this.getServerFallback().box(content, options);
4337
+ return;
4338
+ }
4339
+ const colorCap = getColorCapability();
4340
+ const output = renderBox(content, options, colorCap);
4341
+ process.stderr.write(output + "\n");
4342
+ }
4343
+ /**
4344
+ * Renders an array of objects as a formatted ASCII table.
4345
+ * Note: This is distinct from the existing table() method which uses console.table.
4346
+ *
4347
+ * @param {Record<string, unknown>[]} rows - Array of row objects
4348
+ * @param {ITableOptions} options - Table rendering options
4349
+ *
4350
+ * @example
4351
+ * logger.cliTable([
4352
+ * { provider: 'Groq', status: 'Available', model: 'llama-3.3-70b' },
4353
+ * { provider: 'Gemini', status: 'Configured', model: 'gemini-2.5-flash' },
4354
+ * ]);
4355
+ *
4356
+ * @since 5.0.0
4357
+ */
4358
+ cliTable(rows, options) {
4359
+ if (!this._showPrimitives) return;
4360
+ if (!isRunningInTerminal()) {
4361
+ this.getServerFallback().cliTable(rows, options);
4362
+ return;
4363
+ }
4364
+ const colorCap = getColorCapability();
4365
+ const output = renderTable(rows, options, colorCap);
4366
+ process.stderr.write(output + "\n");
4367
+ }
4368
+ /**
4369
+ * Creates a spinner handle for showing progress during async operations.
4370
+ * Returns a NoopSpinner in non-TTY environments.
4371
+ *
4372
+ * @param {string} message - Initial spinner text
4373
+ * @returns {ISpinnerHandle} Spinner controller
4374
+ *
4375
+ * @example
4376
+ * const s = logger.spinner('Analyzing repository...');
4377
+ * s.start();
4378
+ * await analyzeRepo();
4379
+ * s.succeed('Analysis complete (1.2s)');
4380
+ *
4381
+ * @since 5.0.0
4382
+ */
4383
+ spinner(message) {
4384
+ if (!isRunningInTerminal() || this.config.outputMode === "silent") {
4385
+ return new NoopSpinner(message, this);
4386
+ }
4387
+ return new SpinnerManager(message, this.config, this);
4388
+ }
4389
+ /**
4390
+ * Sets the CLI verbosity level, controlling both log verbosity and primitive visibility
4391
+ *
4392
+ * @param {CLILogLevel} level - CLI log level
4393
+ *
4394
+ * @example
4395
+ * logger.setCLILevel('quiet'); // Only errors, no CLI primitives
4396
+ * logger.setCLILevel('verbose'); // Debug logs + all CLI primitives
4397
+ *
4398
+ * @since 5.0.0
4399
+ */
4400
+ setCLILevel(level) {
4401
+ const mapping = CLI_LEVEL_MAP[level];
4402
+ this.setVerbosity(mapping.verbosity);
4403
+ this._showPrimitives = mapping.showPrimitives;
4404
+ this.config.cliLevel = level;
4405
+ }
4406
+ /**
4407
+ * Returns the current CLI log level
4408
+ * @returns {CLILogLevel} Current CLI log level
4409
+ * @since 5.0.0
4410
+ */
4411
+ get cliLevel() {
4412
+ return this.config.cliLevel ?? "normal";
4413
+ }
4414
+ /** Lazily creates the server fallback instance @private */
4415
+ getServerFallback() {
4416
+ if (!this._serverFallback) {
4417
+ this._serverFallback = new ServerFallback(this);
4418
+ }
4419
+ return this._serverFallback;
4420
+ }
4421
+ // ===== OUTPUT WRITER SYSTEM =====
4422
+ /**
4423
+ * Writes formatted output to the configured destination.
4424
+ * Respects outputMode configuration for console, silent, or custom output.
4425
+ *
4426
+ * @private
4427
+ * @param {string} message - Formatted log message
4428
+ * @param {LogLevel} level - Log level
4429
+ * @param {string[]} styles - CSS styles for browser console
4430
+ * @param {any[]} additionalArgs - Additional arguments to log
4431
+ * @since 4.0.0
4432
+ */
4433
+ writeOutput(message, level, styles2, additionalArgs) {
4434
+ const mode = this.config.outputMode ?? "console";
4435
+ if (mode === "silent") {
4436
+ return;
4437
+ }
4438
+ if (mode === "custom" && this.config.outputWriter) {
4439
+ const fullMessage = additionalArgs.length > 0 ? `${message} ${additionalArgs.map((a) => String(a)).join(" ")}` : message;
4440
+ this.config.outputWriter.write(fullMessage, level, styles2);
4441
+ return;
4442
+ }
4443
+ if (additionalArgs.length > 0) {
4444
+ console.log(message, ...styles2, ...additionalArgs);
4445
+ } else {
4446
+ console.log(message, ...styles2);
4447
+ }
4448
+ }
4449
+ // ===== CLI SYSTEM =====
4450
+ /**
4451
+ * Procesador de comandos CLI para configuración y exportación del logger
4452
+ *
4453
+ * @param {string} command - Comando CLI a ejecutar
4454
+ * @returns {Promise<void>}
4455
+ *
4456
+ * @example
4457
+ * // Comandos disponibles
4458
+ * await logger.cli('export json'); // Exporta logs en JSON
4459
+ * await logger.cli('export csv'); // Exporta logs en CSV
4460
+ * await logger.cli('theme list'); // Lista temas disponibles
4461
+ * await logger.cli('theme set neon'); // Cambia al tema neon
4462
+ * await logger.cli('config show'); // Muestra configuración actual
4463
+ * await logger.cli('history clear'); // Limpia historial de logs
4464
+ * await logger.cli('status'); // Muestra estado del logger
4465
+ * await logger.cli('help'); // Muestra ayuda de comandos
4466
+ *
4467
+ * @since 0.3.0
4468
+ */
4469
+ async cli(command) {
4470
+ if (!this.cliProcessor) {
4471
+ this.error("CLI processor not initialized");
4472
+ return;
4473
+ }
4474
+ await this.cliProcessor.processCommand(command, this);
4475
+ }
4476
+ }
4477
+ let _defaultLogger = null;
4478
+ function getDefaultLogger() {
4479
+ if (!_defaultLogger) {
4480
+ _defaultLogger = new Logger({
4481
+ verbosity: "info",
4482
+ enableColors: true,
4483
+ enableTimestamps: true,
4484
+ enableStackTrace: true,
4485
+ bufferSize: 1e3
4486
+ // Enable export functionality by default
4487
+ });
4488
+ try {
4489
+ displayInitBanner();
4490
+ } catch (error2) {
4491
+ }
4492
+ }
4493
+ return _defaultLogger;
4494
+ }
4495
+ getDefaultLogger();
4496
+ export {
4497
+ APILogger as A,
4498
+ BANNER_VARIANTS as B,
4499
+ ComponentLogger as C,
4500
+ ExportLogHandler as E,
4501
+ HookManager as H,
4502
+ Logger as L,
4503
+ SerializerRegistry as S,
4504
+ THEME_PRESETS as T,
4505
+ THEME_BANNERS as a,
4506
+ TransportManager as b,
4507
+ ScopedLogger as c,
4508
+ displayInitBanner as d,
4509
+ ContextLogger as e
4510
+ };
4511
+ //# sourceMappingURL=Logger-D_vuKP4l.js.map