@mks2508/better-logger 0.14.0-alpha.2 → 0.18.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/README.md +50 -244
  2. package/dist/Logger.d.ts +662 -202
  3. package/dist/Logger.d.ts.map +1 -1
  4. package/dist/ScopedLogger.d.ts +434 -175
  5. package/dist/ScopedLogger.d.ts.map +1 -1
  6. package/dist/chunks/HookBridge-C-AvXmPD.cjs +504 -0
  7. package/dist/chunks/HookBridge-C-AvXmPD.cjs.map +1 -0
  8. package/dist/chunks/HookBridge-CI2PH79S.js +487 -0
  9. package/dist/chunks/HookBridge-CI2PH79S.js.map +1 -0
  10. package/dist/chunks/LogContext-BaMXleWj.cjs +105 -0
  11. package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
  12. package/dist/chunks/LogContext-DjlITOzZ.js +100 -0
  13. package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
  14. package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
  15. package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
  16. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
  17. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
  18. package/dist/chunks/StyleManager-DQ6UNRB-.cjs +118 -0
  19. package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
  20. package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
  21. package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
  22. package/dist/chunks/core-Blfi2klP.js +31 -0
  23. package/dist/chunks/core-Blfi2klP.js.map +1 -0
  24. package/dist/chunks/core-CqS_UBzJ.cjs +36 -0
  25. package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
  26. package/dist/chunks/environment-detector-7NvnYUfr.js +110 -0
  27. package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
  28. package/dist/chunks/environment-detector-D-tHkKWA.cjs +163 -0
  29. package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
  30. package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
  31. package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
  32. package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
  33. package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
  34. package/dist/chunks/spinner-BHyYEXsM.cjs +1029 -0
  35. package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
  36. package/dist/chunks/spinner-BtkwpzYv.js +982 -0
  37. package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
  38. package/dist/chunks/styling-CRw3KQW4.js +1592 -0
  39. package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
  40. package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
  41. package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
  42. package/dist/chunks/transports-BGfwwakw.js +1237 -0
  43. package/dist/chunks/transports-BGfwwakw.js.map +1 -0
  44. package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
  45. package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
  46. package/dist/chunks/utils-W_cxqriN.cjs +705 -0
  47. package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
  48. package/dist/chunks/utils-tKfBAWUM.js +586 -0
  49. package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
  50. package/dist/cli/CommandProcessor.d.ts +166 -19
  51. package/dist/cli/CommandProcessor.d.ts.map +1 -1
  52. package/dist/cli/commands/ConfigCommand.d.ts +36 -1
  53. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
  54. package/dist/cli/commands/ExportCommand.d.ts +54 -26
  55. package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
  56. package/dist/cli/commands/ThemeCommand.d.ts +62 -3
  57. package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
  58. package/dist/cli/help.d.ts +30 -2
  59. package/dist/cli/help.d.ts.map +1 -1
  60. package/dist/cli/index.d.ts +30 -4
  61. package/dist/cli/index.d.ts.map +1 -1
  62. package/dist/cli-module.d.ts +13 -0
  63. package/dist/cli-module.d.ts.map +1 -0
  64. package/dist/cli.cjs +11 -0
  65. package/dist/cli.js +3 -0
  66. package/dist/constants.d.ts +16 -47
  67. package/dist/constants.d.ts.map +1 -1
  68. package/dist/context/LogContext.d.ts +245 -0
  69. package/dist/context/LogContext.d.ts.map +1 -0
  70. package/dist/context/index.d.ts +6 -0
  71. package/dist/context/index.d.ts.map +1 -0
  72. package/dist/context-module.d.ts +6 -0
  73. package/dist/context-module.d.ts.map +1 -0
  74. package/dist/context.cjs +3 -0
  75. package/dist/context.js +2 -0
  76. package/dist/core.cjs +304 -2
  77. package/dist/core.cjs.map +1 -1
  78. package/dist/core.d.ts +56 -34
  79. package/dist/core.d.ts.map +1 -1
  80. package/dist/core.js +281 -314
  81. package/dist/core.js.map +1 -1
  82. package/dist/hooks/HookBridge.d.ts +32 -0
  83. package/dist/hooks/HookBridge.d.ts.map +1 -0
  84. package/dist/hooks/HookManager.d.ts +319 -0
  85. package/dist/hooks/HookManager.d.ts.map +1 -0
  86. package/dist/hooks/index.d.ts +7 -0
  87. package/dist/hooks/index.d.ts.map +1 -0
  88. package/dist/hooks-module.d.ts +7 -0
  89. package/dist/hooks-module.d.ts.map +1 -0
  90. package/dist/hooks.cjs +5 -0
  91. package/dist/hooks.js +2 -0
  92. package/dist/index.cjs +3402 -2
  93. package/dist/index.cjs.map +1 -1
  94. package/dist/index.d.ts +42 -130
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +3327 -158
  97. package/dist/index.js.map +1 -1
  98. package/dist/node-module.d.ts +10 -0
  99. package/dist/node-module.d.ts.map +1 -0
  100. package/dist/node.cjs +13 -0
  101. package/dist/node.cjs.map +1 -0
  102. package/dist/node.js +12 -0
  103. package/dist/node.js.map +1 -0
  104. package/dist/playground/TerminalBridge.d.ts +53 -0
  105. package/dist/playground/TerminalBridge.d.ts.map +1 -0
  106. package/dist/playground/box.d.ts +45 -0
  107. package/dist/playground/box.d.ts.map +1 -0
  108. package/dist/playground/cli-table.d.ts +50 -0
  109. package/dist/playground/cli-table.d.ts.map +1 -0
  110. package/dist/playground/divider.d.ts +29 -0
  111. package/dist/playground/divider.d.ts.map +1 -0
  112. package/dist/playground/header.d.ts +28 -0
  113. package/dist/playground/header.d.ts.map +1 -0
  114. package/dist/playground/index.d.ts +11 -0
  115. package/dist/playground/index.d.ts.map +1 -0
  116. package/dist/playground/server-fallback.d.ts +114 -0
  117. package/dist/playground/server-fallback.d.ts.map +1 -0
  118. package/dist/playground/spinner.d.ts +197 -0
  119. package/dist/playground/spinner.d.ts.map +1 -0
  120. package/dist/playground/step.d.ts +33 -0
  121. package/dist/playground/step.d.ts.map +1 -0
  122. package/dist/playground-module.d.ts +11 -0
  123. package/dist/playground-module.d.ts.map +1 -0
  124. package/dist/playground.cjs +9 -0
  125. package/dist/playground.js +2 -0
  126. package/dist/serializers/SerializerBridge.d.ts +28 -0
  127. package/dist/serializers/SerializerBridge.d.ts.map +1 -0
  128. package/dist/serializers/SerializerRegistry.d.ts +252 -0
  129. package/dist/serializers/SerializerRegistry.d.ts.map +1 -0
  130. package/dist/serializers/index.d.ts +7 -0
  131. package/dist/serializers/index.d.ts.map +1 -0
  132. package/dist/serializers-module.d.ts +7 -0
  133. package/dist/serializers-module.d.ts.map +1 -0
  134. package/dist/serializers.cjs +5 -0
  135. package/dist/serializers.js +2 -0
  136. package/dist/styles/StyleManager.d.ts +190 -0
  137. package/dist/styles/StyleManager.d.ts.map +1 -0
  138. package/dist/styles/index.d.ts +7 -0
  139. package/dist/styles/index.d.ts.map +1 -0
  140. package/dist/styles-module.d.ts +7 -0
  141. package/dist/styles-module.d.ts.map +1 -0
  142. package/dist/styles.cjs +7 -0
  143. package/dist/styles.js +3 -0
  144. package/dist/styling/SmartPresets.d.ts +100 -6
  145. package/dist/styling/SmartPresets.d.ts.map +1 -1
  146. package/dist/styling/StyleBuilder.d.ts +453 -32
  147. package/dist/styling/StyleBuilder.d.ts.map +1 -1
  148. package/dist/styling/banners.d.ts +85 -5
  149. package/dist/styling/banners.d.ts.map +1 -1
  150. package/dist/styling/index.d.ts +8 -3
  151. package/dist/styling/index.d.ts.map +1 -1
  152. package/dist/styling/themes.d.ts +41 -2
  153. package/dist/styling/themes.d.ts.map +1 -1
  154. package/dist/terminal/color-converter.d.ts +73 -0
  155. package/dist/terminal/color-converter.d.ts.map +1 -0
  156. package/dist/terminal/formatter.d.ts +23 -0
  157. package/dist/terminal/formatter.d.ts.map +1 -0
  158. package/dist/transports/ConsoleTransport.d.ts +104 -0
  159. package/dist/transports/ConsoleTransport.d.ts.map +1 -0
  160. package/dist/transports/FileTransport.d.ts +137 -0
  161. package/dist/transports/FileTransport.d.ts.map +1 -0
  162. package/dist/transports/HttpTransport.d.ts +180 -0
  163. package/dist/transports/HttpTransport.d.ts.map +1 -0
  164. package/dist/transports/OtlpTransport.d.ts +165 -0
  165. package/dist/transports/OtlpTransport.d.ts.map +1 -0
  166. package/dist/transports/TransportBridge.d.ts +43 -0
  167. package/dist/transports/TransportBridge.d.ts.map +1 -0
  168. package/dist/transports/TransportManager.d.ts +251 -0
  169. package/dist/transports/TransportManager.d.ts.map +1 -0
  170. package/dist/transports/index.d.ts +6 -0
  171. package/dist/transports/index.d.ts.map +1 -0
  172. package/dist/transports-module.d.ts +10 -0
  173. package/dist/transports-module.d.ts.map +1 -0
  174. package/dist/transports.cjs +7 -0
  175. package/dist/transports.js +2 -0
  176. package/dist/types/core.d.ts +295 -17
  177. package/dist/types/core.d.ts.map +1 -1
  178. package/dist/types/handlers.d.ts +0 -67
  179. package/dist/types/handlers.d.ts.map +1 -1
  180. package/dist/types/hooks.d.ts +138 -0
  181. package/dist/types/hooks.d.ts.map +1 -0
  182. package/dist/types/index.d.ts +7 -3
  183. package/dist/types/index.d.ts.map +1 -1
  184. package/dist/types/serializers.d.ts +97 -0
  185. package/dist/types/serializers.d.ts.map +1 -0
  186. package/dist/types/transports.d.ts +132 -0
  187. package/dist/types/transports.d.ts.map +1 -0
  188. package/dist/utils/ansi-colors.d.ts +115 -0
  189. package/dist/utils/ansi-colors.d.ts.map +1 -0
  190. package/dist/utils/environment-detector.d.ts +53 -0
  191. package/dist/utils/environment-detector.d.ts.map +1 -0
  192. package/dist/utils/formatting.d.ts +9 -8
  193. package/dist/utils/formatting.d.ts.map +1 -1
  194. package/dist/utils/index.d.ts +3 -2
  195. package/dist/utils/index.d.ts.map +1 -1
  196. package/dist/utils/output.d.ts +14 -17
  197. package/dist/utils/output.d.ts.map +1 -1
  198. package/dist/utils/stackTrace.d.ts +2 -2
  199. package/dist/utils/stackTrace.d.ts.map +1 -1
  200. package/dist/utils/timestamps.d.ts +0 -12
  201. package/dist/utils/timestamps.d.ts.map +1 -1
  202. package/package.json +95 -21
  203. package/.claude/settings.local.json +0 -39
  204. package/.github/workflows/ci-quality.yml +0 -357
  205. package/.github/workflows/docs-demo.yml +0 -119
  206. package/.github/workflows/releases-core.yml +0 -512
  207. package/.github/workflows/releases-full.yml +0 -582
  208. package/.github/workflows-backup/ci.yml +0 -221
  209. package/.github/workflows-backup/nightly.yml +0 -196
  210. package/.github/workflows-backup/release-optimized.yml +0 -373
  211. package/.github/workflows-backup/release.yml +0 -269
  212. package/.release-notes-0.2.0.md +0 -129
  213. package/.yamllint +0 -28
  214. package/CHANGELOG.json +0 -865
  215. package/CLAUDE.md +0 -204
  216. package/bun.lock +0 -323
  217. package/demo.html +0 -847
  218. package/dist/.tsbuildinfo +0 -1
  219. package/dist/Logger.js +0 -1124
  220. package/dist/ScopedLogger.js +0 -426
  221. package/dist/chunks/Logger-Crw1woqR.js +0 -3464
  222. package/dist/chunks/Logger-Crw1woqR.js.map +0 -1
  223. package/dist/chunks/Logger-D_p3xnbq.js +0 -2
  224. package/dist/chunks/Logger-D_p3xnbq.js.map +0 -1
  225. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js +0 -33
  226. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js.map +0 -1
  227. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js +0 -2
  228. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js.map +0 -1
  229. package/dist/chunks/environment-Bxbnw4pd.js +0 -544
  230. package/dist/chunks/environment-Bxbnw4pd.js.map +0 -1
  231. package/dist/chunks/environment-Dm66zOML.js +0 -4
  232. package/dist/chunks/environment-Dm66zOML.js.map +0 -1
  233. package/dist/chunks/formatting-C0riPC5_.js +0 -95
  234. package/dist/chunks/formatting-C0riPC5_.js.map +0 -1
  235. package/dist/chunks/formatting-DNCAV66-.js +0 -2
  236. package/dist/chunks/formatting-DNCAV66-.js.map +0 -1
  237. package/dist/cli/CommandProcessor.js +0 -184
  238. package/dist/cli/commands/ConfigCommand.js +0 -88
  239. package/dist/cli/commands/ExportCommand.js +0 -243
  240. package/dist/cli/commands/HistoryCommand.d.ts +0 -50
  241. package/dist/cli/commands/HistoryCommand.d.ts.map +0 -1
  242. package/dist/cli/commands/HistoryCommand.js +0 -96
  243. package/dist/cli/commands/StatusCommand.d.ts +0 -33
  244. package/dist/cli/commands/StatusCommand.d.ts.map +0 -1
  245. package/dist/cli/commands/StatusCommand.js +0 -93
  246. package/dist/cli/commands/ThemeCommand.js +0 -79
  247. package/dist/cli/help.js +0 -118
  248. package/dist/cli/index.js +0 -46
  249. package/dist/constants.js +0 -159
  250. package/dist/example.d.ts +0 -18
  251. package/dist/example.d.ts.map +0 -1
  252. package/dist/example.js +0 -154
  253. package/dist/exports-module.d.ts +0 -203
  254. package/dist/exports-module.d.ts.map +0 -1
  255. package/dist/exports-module.js +0 -260
  256. package/dist/exports.cjs +0 -2
  257. package/dist/exports.cjs.map +0 -1
  258. package/dist/exports.js +0 -238
  259. package/dist/exports.js.map +0 -1
  260. package/dist/handlers/AnalyticsLogHandler.d.ts +0 -11
  261. package/dist/handlers/AnalyticsLogHandler.d.ts.map +0 -1
  262. package/dist/handlers/AnalyticsLogHandler.js +0 -19
  263. package/dist/handlers/ExportLogHandler.d.ts +0 -103
  264. package/dist/handlers/ExportLogHandler.d.ts.map +0 -1
  265. package/dist/handlers/ExportLogHandler.js +0 -516
  266. package/dist/handlers/FileLogHandler.d.ts +0 -36
  267. package/dist/handlers/FileLogHandler.d.ts.map +0 -1
  268. package/dist/handlers/FileLogHandler.js +0 -156
  269. package/dist/handlers/RemoteLogHandler.d.ts +0 -14
  270. package/dist/handlers/RemoteLogHandler.d.ts.map +0 -1
  271. package/dist/handlers/RemoteLogHandler.js +0 -37
  272. package/dist/handlers/index.d.ts +0 -8
  273. package/dist/handlers/index.d.ts.map +0 -1
  274. package/dist/handlers/index.js +0 -7
  275. package/dist/main.d.ts +0 -2
  276. package/dist/main.d.ts.map +0 -1
  277. package/dist/main.js +0 -139
  278. package/dist/styling/LogStyleBuilder.d.ts +0 -149
  279. package/dist/styling/LogStyleBuilder.d.ts.map +0 -1
  280. package/dist/styling/LogStyleBuilder.js +0 -289
  281. package/dist/styling/SemanticStyles.d.ts +0 -181
  282. package/dist/styling/SemanticStyles.d.ts.map +0 -1
  283. package/dist/styling/SemanticStyles.js +0 -339
  284. package/dist/styling/SmartPresets.js +0 -276
  285. package/dist/styling/StyleBuilder.js +0 -280
  286. package/dist/styling/banners.js +0 -155
  287. package/dist/styling/index.js +0 -9
  288. package/dist/styling/themes.js +0 -231
  289. package/dist/styling-module.d.ts +0 -185
  290. package/dist/styling-module.d.ts.map +0 -1
  291. package/dist/styling-module.js +0 -199
  292. package/dist/styling.cjs +0 -2
  293. package/dist/styling.cjs.map +0 -1
  294. package/dist/styling.js +0 -146
  295. package/dist/styling.js.map +0 -1
  296. package/dist/types/Logger.d.ts +0 -700
  297. package/dist/types/Logger.d.ts.map +0 -1
  298. package/dist/types/ScopedLogger.d.ts +0 -310
  299. package/dist/types/ScopedLogger.d.ts.map +0 -1
  300. package/dist/types/cli/CommandProcessor.d.ts +0 -100
  301. package/dist/types/cli/CommandProcessor.d.ts.map +0 -1
  302. package/dist/types/cli/commands/ConfigCommand.d.ts +0 -14
  303. package/dist/types/cli/commands/ConfigCommand.d.ts.map +0 -1
  304. package/dist/types/cli/commands/ExportCommand.d.ts +0 -48
  305. package/dist/types/cli/commands/ExportCommand.d.ts.map +0 -1
  306. package/dist/types/cli/commands/HistoryCommand.d.ts +0 -47
  307. package/dist/types/cli/commands/HistoryCommand.d.ts.map +0 -1
  308. package/dist/types/cli/commands/StatusCommand.d.ts +0 -30
  309. package/dist/types/cli/commands/StatusCommand.d.ts.map +0 -1
  310. package/dist/types/cli/commands/ThemeCommand.d.ts +0 -30
  311. package/dist/types/cli/commands/ThemeCommand.d.ts.map +0 -1
  312. package/dist/types/cli/help.d.ts +0 -12
  313. package/dist/types/cli/help.d.ts.map +0 -1
  314. package/dist/types/cli/index.d.ts +0 -15
  315. package/dist/types/cli/index.d.ts.map +0 -1
  316. package/dist/types/constants.d.ts +0 -119
  317. package/dist/types/constants.d.ts.map +0 -1
  318. package/dist/types/core.js +0 -28
  319. package/dist/types/example.d.ts +0 -18
  320. package/dist/types/example.d.ts.map +0 -1
  321. package/dist/types/exports-module.d.ts +0 -196
  322. package/dist/types/exports-module.d.ts.map +0 -1
  323. package/dist/types/handlers/AnalyticsLogHandler.d.ts +0 -8
  324. package/dist/types/handlers/AnalyticsLogHandler.d.ts.map +0 -1
  325. package/dist/types/handlers/ExportLogHandler.d.ts +0 -100
  326. package/dist/types/handlers/ExportLogHandler.d.ts.map +0 -1
  327. package/dist/types/handlers/FileLogHandler.d.ts +0 -33
  328. package/dist/types/handlers/FileLogHandler.d.ts.map +0 -1
  329. package/dist/types/handlers/RemoteLogHandler.d.ts +0 -11
  330. package/dist/types/handlers/RemoteLogHandler.d.ts.map +0 -1
  331. package/dist/types/handlers/index.d.ts +0 -8
  332. package/dist/types/handlers/index.d.ts.map +0 -1
  333. package/dist/types/handlers.js +0 -4
  334. package/dist/types/index.js +0 -4
  335. package/dist/types/main.d.ts +0 -2
  336. package/dist/types/main.d.ts.map +0 -1
  337. package/dist/types/styling/LogStyleBuilder.d.ts +0 -146
  338. package/dist/types/styling/LogStyleBuilder.d.ts.map +0 -1
  339. package/dist/types/styling/SemanticStyles.d.ts +0 -178
  340. package/dist/types/styling/SemanticStyles.d.ts.map +0 -1
  341. package/dist/types/styling/SmartPresets.d.ts +0 -22
  342. package/dist/types/styling/SmartPresets.d.ts.map +0 -1
  343. package/dist/types/styling/StyleBuilder.d.ts +0 -140
  344. package/dist/types/styling/StyleBuilder.d.ts.map +0 -1
  345. package/dist/types/styling/banners.d.ts +0 -42
  346. package/dist/types/styling/banners.d.ts.map +0 -1
  347. package/dist/types/styling/index.d.ts +0 -10
  348. package/dist/types/styling/index.d.ts.map +0 -1
  349. package/dist/types/styling/themes.d.ts +0 -7
  350. package/dist/types/styling/themes.d.ts.map +0 -1
  351. package/dist/types/styling-module.d.ts +0 -178
  352. package/dist/types/styling-module.d.ts.map +0 -1
  353. package/dist/types/types/core.d.ts +0 -221
  354. package/dist/types/types/core.d.ts.map +0 -1
  355. package/dist/types/types/handlers.d.ts +0 -85
  356. package/dist/types/types/handlers.d.ts.map +0 -1
  357. package/dist/types/types/index.d.ts +0 -7
  358. package/dist/types/types/index.d.ts.map +0 -1
  359. package/dist/types/utils/environment.d.ts +0 -47
  360. package/dist/types/utils/environment.d.ts.map +0 -1
  361. package/dist/types/utils/formatting.d.ts +0 -37
  362. package/dist/types/utils/formatting.d.ts.map +0 -1
  363. package/dist/types/utils/index.d.ts +0 -7
  364. package/dist/types/utils/index.d.ts.map +0 -1
  365. package/dist/types/utils/opentui-detection.d.ts +0 -34
  366. package/dist/types/utils/opentui-detection.d.ts.map +0 -1
  367. package/dist/types/utils/output.d.ts +0 -41
  368. package/dist/types/utils/output.d.ts.map +0 -1
  369. package/dist/types/utils/stackTrace.d.ts +0 -6
  370. package/dist/types/utils/stackTrace.d.ts.map +0 -1
  371. package/dist/types/utils/timestamps.d.ts +0 -20
  372. package/dist/types/utils/timestamps.d.ts.map +0 -1
  373. package/dist/utils/environment.d.ts +0 -47
  374. package/dist/utils/environment.d.ts.map +0 -1
  375. package/dist/utils/environment.js +0 -85
  376. package/dist/utils/formatting.js +0 -117
  377. package/dist/utils/index.js +0 -6
  378. package/dist/utils/opentui-detection.d.ts +0 -34
  379. package/dist/utils/opentui-detection.d.ts.map +0 -1
  380. package/dist/utils/opentui-detection.js +0 -116
  381. package/dist/utils/output.js +0 -150
  382. package/dist/utils/stackTrace.js +0 -81
  383. package/dist/utils/timestamps.js +0 -71
  384. package/dist/vite.svg +0 -1
  385. package/docs/API.md +0 -691
  386. package/docs/CORE.md +0 -264
  387. package/docs/DEVELOPMENT.md +0 -731
  388. package/docs/EXPORTS.md +0 -467
  389. package/docs/PACKAGES.md +0 -244
  390. package/docs/STYLING.md +0 -405
  391. package/docs/_config.yml +0 -36
  392. package/docs/index.md +0 -179
  393. package/examples/README.md +0 -208
  394. package/examples/basic-logging.js +0 -75
  395. package/examples/data-export.js +0 -234
  396. package/examples/package.json +0 -16
  397. package/examples/performance-timing.js +0 -170
  398. package/examples/simplified-api.js +0 -124
  399. package/examples/styling-themes.js +0 -207
  400. package/index.html +0 -358
  401. package/packages/core/package.json +0 -57
  402. package/packages/exports/package.json +0 -41
  403. package/packages/nodejs-opentui/README.md +0 -232
  404. package/packages/nodejs-opentui/package.json +0 -72
  405. package/packages/nodejs-opentui/src/LogRenderer.ts +0 -171
  406. package/packages/nodejs-opentui/src/OpenTUILogHandler.ts +0 -178
  407. package/packages/nodejs-opentui/src/components/LogBadge.tsx +0 -131
  408. package/packages/nodejs-opentui/src/index.ts +0 -133
  409. package/packages/nodejs-opentui/src/types.ts +0 -158
  410. package/packages/nodejs-opentui/tsconfig.json +0 -20
  411. package/packages/styling/package.json +0 -41
  412. package/project-utils/README.md +0 -172
  413. package/project-utils/auto-release-gemini.ts +0 -1193
  414. package/project-utils/auto-release-ui.ts +0 -1329
  415. package/project-utils/commit-generator.ts +0 -1385
  416. package/project-utils/commit-ui.ts +0 -264
  417. package/project-utils/git-utils.ts +0 -199
  418. package/project-utils/github-release-manager.ts +0 -466
  419. package/project-utils/project-config.ts +0 -260
  420. package/project-utils/prompt-templates.js +0 -345
  421. package/project-utils/prompt-templates.ts +0 -422
  422. package/project-utils/version-manager.ts +0 -1078
  423. package/public/vite.svg +0 -1
  424. package/src/Logger.ts +0 -1276
  425. package/src/ScopedLogger.ts +0 -454
  426. package/src/cli/CommandProcessor.ts +0 -248
  427. package/src/cli/commands/ConfigCommand.ts +0 -93
  428. package/src/cli/commands/ExportCommand.ts +0 -276
  429. package/src/cli/commands/HistoryCommand.ts +0 -117
  430. package/src/cli/commands/StatusCommand.ts +0 -112
  431. package/src/cli/commands/ThemeCommand.ts +0 -88
  432. package/src/cli/help.ts +0 -127
  433. package/src/cli/index.ts +0 -71
  434. package/src/constants.ts +0 -171
  435. package/src/core.ts +0 -393
  436. package/src/example.ts +0 -210
  437. package/src/exports-module.ts +0 -311
  438. package/src/handlers/AnalyticsLogHandler.ts +0 -22
  439. package/src/handlers/ExportLogHandler.ts +0 -609
  440. package/src/handlers/FileLogHandler.ts +0 -169
  441. package/src/handlers/RemoteLogHandler.ts +0 -42
  442. package/src/handlers/index.ts +0 -8
  443. package/src/index.ts +0 -209
  444. package/src/main.ts +0 -196
  445. package/src/style.css +0 -96
  446. package/src/styling/LogStyleBuilder.ts +0 -355
  447. package/src/styling/SemanticStyles.ts +0 -380
  448. package/src/styling/SmartPresets.ts +0 -288
  449. package/src/styling/StyleBuilder.ts +0 -319
  450. package/src/styling/banners.ts +0 -168
  451. package/src/styling/index.ts +0 -27
  452. package/src/styling/themes.ts +0 -235
  453. package/src/styling-module.ts +0 -244
  454. package/src/types/core.ts +0 -236
  455. package/src/types/handlers.ts +0 -95
  456. package/src/types/index.ts +0 -35
  457. package/src/typescript.svg +0 -1
  458. package/src/utils/environment.ts +0 -94
  459. package/src/utils/formatting.ts +0 -142
  460. package/src/utils/index.ts +0 -21
  461. package/src/utils/opentui-detection.ts +0 -138
  462. package/src/utils/output.ts +0 -185
  463. package/src/utils/stackTrace.ts +0 -95
  464. package/src/utils/timestamps.ts +0 -80
  465. package/src/vite-env.d.ts +0 -1
  466. package/test-core-browser.html +0 -237
  467. package/test-core-node.js +0 -63
  468. package/tests/test-conflict-resolution.ts +0 -391
  469. package/tests/validate-workflows.sh +0 -131
  470. package/tests/yaml-autofix.sh +0 -146
  471. package/tsconfig.json +0 -50
  472. package/vite.config.ts +0 -223
package/dist/index.js CHANGED
@@ -1,160 +1,3329 @@
1
+ import { t as LOG_LEVELS } from "./chunks/core-Blfi2klP.js";
2
+ import { o as LOG_LEVEL_TO_SEVERITY_NUMBER, s as LOG_LEVEL_TO_SEVERITY_TEXT, t as TransportManager } from "./chunks/transports-BGfwwakw.js";
3
+ import { _ as DEFAULT_CONFIG, a as safeSerialize, b as parseStackTrace, c as ansiBackground, d as ansiDim, f as ansiStyle, g as CLI_LEVEL_MAP, h as formatSuccessANSI, i as getConsoleMethod, l as ansiBold, m as formatLogLevelANSI, o as createStyledOutput, p as ansiUnderline, r as formatTablePlain, s as setupThemeChangeListener, t as createLogEntry, u as ansiColor, y as formatTimestamp } from "./chunks/utils-tKfBAWUM.js";
4
+ import { a as THEME_BANNERS, c as StyleBuilder, i as BANNER_VARIANTS, l as StylePresets, n as getSmartPreset, o as displayInitBanner, r as hasPreset, s as THEME_PRESETS, t as getAvailablePresets } from "./chunks/styling-CRw3KQW4.js";
5
+ import { a as getTerminalWidth, c as isRunningInTerminal, i as getTerminalHeight, l as supportsANSI, n as getEnvironment, r as getEnvironmentInfo, t as getColorCapability } from "./chunks/environment-detector-7NvnYUfr.js";
6
+ import { a as renderDivider, c as formatBadge, i as renderBox, n as SpinnerManager, o as renderHeader, r as renderTable, s as renderStep, t as NoopSpinner } from "./chunks/spinner-BtkwpzYv.js";
7
+ import { t as createLogContext } from "./chunks/LogContext-DjlITOzZ.js";
8
+ import { t as createHookBridge } from "./chunks/HookBridge-CI2PH79S.js";
9
+ import { t as createSerializerBridge } from "./chunks/SerializerBridge-Ba43Mk7j.js";
10
+ import { t as ServerFallback } from "./chunks/server-fallback-jj0T6XaK.js";
11
+ import { t as createStyleManager } from "./chunks/StyleManager-DjwAYbxE.js";
12
+ //#region src/ScopedLogger.ts
1
13
  /**
2
- * @fileoverview Better Logger - Librería completa con todas las características
3
- * @version 0.3.0
4
- * @since 2024
5
- *
6
- * Punto de entrada principal que proporciona la experiencia completa de Better Logger
7
- * con características avanzadas incluyendo estilos CSS, soporte SVG, animaciones,
8
- * capacidades de exportación y logging remoto.
9
- *
10
- * @module @mks2508/better-logger
11
- */
12
- // Main Logger class with all features
13
- import { Logger } from './Logger.js';
14
- // Create singleton instance with all features enabled
15
- const logger = new Logger();
16
- /**
17
- * Clase principal Logger con conjunto completo de características
18
- *
19
- * @example
20
- * // Importación y uso básico
21
- * import { Logger } from '@mks2508/better-logger';
22
- *
23
- * const logger = new Logger();
24
- * logger.preset('cyberpunk'); // Aplicar preset completo
25
- * logger.info('¡Hola mundo!');
26
- *
27
- * @example
28
- * // Logger con scope para componentes
29
- * const auth = logger.component('Auth');
30
- * auth.info('Usuario autenticando...');
31
- * auth.success('Login exitoso');
32
- *
33
- * @example
34
- * // Logger para APIs con badges
35
- * const api = logger.api('GraphQL');
36
- * api.badges(['v2', 'cached']).info('Query ejecutada');
37
- *
38
- * @since 0.3.0
39
- */
40
- export { Logger };
41
- /**
42
- * Instancia singleton del logger lista para usar
43
- * @default
44
- *
45
- * @example
46
- * // Uso directo sin crear instancia
47
- * import logger from '@mks2508/better-logger';
48
- *
49
- * logger.info('Aplicación iniciada');
50
- * logger.success('Conexión establecida');
51
- * logger.warn('Memoria al 80%');
52
- * logger.error('Fallo en conexión');
53
- */
54
- export default logger;
55
- /**
56
- * Métodos de logging individuales (enlazados al singleton)
57
- *
58
- * @example
59
- * // Importar solo los métodos necesarios
60
- * import { info, error, success } from '@mks2508/better-logger';
61
- *
62
- * info('Proceso iniciado');
63
- * success('✓ Completado exitosamente');
64
- * error('Error:', errorDetails);
65
- *
66
- * @since 0.3.0
67
- */
68
- export const debug = (...args) => logger.debug(...args);
69
- export const info = (...args) => logger.info(...args);
70
- export const warn = (...args) => logger.warn(...args);
71
- export const error = (...args) => logger.error(...args);
72
- export const success = (...args) => logger.success(...args);
73
- export const critical = (...args) => logger.critical(...args);
74
- export const trace = (...args) => logger.trace(...args);
75
- export const table = (data, columns) => logger.table(data, columns);
76
- export const group = (label, collapsed) => logger.group(label, collapsed);
77
- export const groupEnd = () => logger.groupEnd();
78
- export const time = (label) => logger.time(label);
79
- export const timeEnd = (label) => logger.timeEnd(label);
80
- export const setGlobalPrefix = (prefix) => logger.setGlobalPrefix(prefix);
81
- export const scope = (prefix) => logger.scope(prefix);
82
- export const setVerbosity = (level) => logger.setVerbosity(level);
83
- export const addHandler = (handler) => logger.addHandler(handler);
84
- export const setTheme = (theme) => logger.setTheme(theme);
85
- export const setBannerType = (bannerType) => logger.setBannerType(bannerType);
86
- export const showBanner = (bannerType) => logger.showBanner(bannerType);
87
- export const logWithSVG = (message, svgContent, options) => logger.logWithSVG(message, svgContent, options);
88
- export const logAnimated = (message, duration) => logger.logAnimated(message, duration);
89
- export const cli = (command) => logger.cli(command);
90
- // Styling utilities
91
- export { StyleBuilder, StylePresets, THEME_PRESETS, THEME_BANNERS, BANNER_VARIANTS } from './styling/index.js';
92
- // Handler exports
93
- export { FileLogHandler, RemoteLogHandler, AnalyticsLogHandler } from './handlers/index.js';
94
- // Constants
95
- export { DEFAULT_CONFIG } from './constants.js';
96
- // Utility exports
97
- export { parseStackTrace, formatTimestamp } from './utils/index.js';
98
- /**
99
- * Utilidades de estilo para crear estilos personalizados de consola
100
- *
101
- * @example
102
- * // Crear estilo personalizado
103
- * import { createStyle, stylePresets } from '@mks2508/better-logger';
104
- *
105
- * const miEstilo = createStyle()
106
- * .bg('linear-gradient(45deg, #ff6b6b, #feca57)')
107
- * .color('white')
108
- * .padding('10px')
109
- * .rounded('8px')
110
- * .bold()
111
- * .build();
112
- *
113
- * console.log('%cMensaje estilizado', miEstilo);
114
- *
115
- * @example
116
- * // Usar presets predefinidos
117
- * console.log('%cÉxito!', stylePresets.success);
118
- * console.log('%cError!', stylePresets.error);
119
- *
120
- * @since 0.3.0
121
- */
122
- import { StyleBuilder, StylePresets } from './styling/index.js';
123
- /**
124
- * Crea una nueva instancia de StyleBuilder para estilos personalizados de consola
125
- *
126
- * @returns {StyleBuilder} Constructor de estilos encadenable
127
- *
128
- * @example
129
- * const estilo = createStyle()
130
- * .gradient('#667eea', '#764ba2')
131
- * .color('white')
132
- * .padding('8px 16px')
133
- * .rounded('4px')
134
- * .shadow('0 2px 4px rgba(0,0,0,0.2)')
135
- * .build();
136
- *
137
- * @since 0.3.0
138
- */
139
- export const createStyle = () => new StyleBuilder();
140
- /**
141
- * Presets de estilo predefinidos para casos de uso comunes
142
- *
143
- * @constant {Object} stylePresets
144
- *
145
- * @example
146
- * console.log('%cOperación exitosa', stylePresets.success);
147
- * console.log('%cAdvertencia', stylePresets.warning);
148
- * console.log('%cError crítico', stylePresets.error);
149
- * console.log('%cInformación', stylePresets.info);
150
- * console.log('%cDestacado', stylePresets.accent);
151
- *
152
- * @since 0.3.0
153
- */
154
- export const stylePresets = {
155
- success: StylePresets.success().build(),
156
- error: StylePresets.error().build(),
157
- warning: StylePresets.warning().build(),
158
- info: StylePresets.info().build(),
159
- accent: StylePresets.accent().build(),
14
+ * Logger prefijado por un scope nominal. Mantiene su propio stack de badges
15
+ * y contextos y delega el envío de mensajes al {@link Logger} padre a través
16
+ * de bindings (`{ scope, badges }`).
17
+ *
18
+ * Es la base de la jerarquía temática: {@link APILogger} y
19
+ * {@link ComponentLogger} extienden de ella, y {@link ContextLogger} la
20
+ * consume para apilar/subdesapilar sub-prefijos en el scope.
21
+ *
22
+ * No se construye directamente: se obtiene con `logger.scope('name')`.
23
+ *
24
+ * @example
25
+ * // El factory method del Logger raíz devuelve un ScopedLogger
26
+ * import logger from '@mks2508/better-logger';
27
+ *
28
+ * const http = logger.scope('HTTP');
29
+ * http.badge('OUTBOUND').info('Request enviada');
30
+ * // salida: [HTTP] [OUTBOUND] Request enviada
31
+ *
32
+ * @example
33
+ * // Anidar contextos dentro de un scope (el prefijo se compone con ':')
34
+ * const retry = http.context('retry');
35
+ * retry.run(() => http.warn('Reintentando petición'));
36
+ * // salida: [HTTP:retry] Reintentando petición
37
+ *
38
+ * @see {@link Logger.scope}
39
+ * @see {@link APILogger}
40
+ * @see {@link ComponentLogger}
41
+ * @see {@link ContextLogger}
42
+ */
43
+ var ScopedLogger = class {
44
+ parent;
45
+ scopeName;
46
+ badgeList = [];
47
+ contextStack = [];
48
+ _timers;
49
+ /**
50
+ * Construye un ScopedLogger vinculado a un {@link Logger} padre.
51
+ *
52
+ * Los clientes no deben llamar a este constructor directamente: usen
53
+ * `logger.scope(name)`, que configura correctamente la instancia.
54
+ *
55
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
56
+ * @param {string} scopeName - Etiqueta del scope; se renderiza como
57
+ * prefijo `[scopeName]` en cada línea.
58
+ */
59
+ constructor(parent, scopeName) {
60
+ this.parent = parent;
61
+ this.scopeName = scopeName;
62
+ }
63
+ get timers() {
64
+ if (!this._timers) this._timers = /* @__PURE__ */ new Map();
65
+ return this._timers;
66
+ }
67
+ getBindings() {
68
+ return {
69
+ scope: this.getScopePrefix(),
70
+ badges: this.badgeList.length > 0 ? [...this.badgeList] : void 0
71
+ };
72
+ }
73
+ getScopePrefix() {
74
+ if (this.contextStack.length === 0) return this.scopeName;
75
+ return [this.scopeName, ...this.contextStack].join(":");
76
+ }
77
+ /**
78
+ * Reemplaza la lista actual de badges por la pasada y la aplica a todos
79
+ * los mensajes posteriores de este scope.
80
+ *
81
+ * @param {string[]} badges - Etiquetas a mostrar como badges adyacentes
82
+ * al prefijo (p. ej. `['OUTBOUND', 'CACHED']`).
83
+ * @returns {this} La misma instancia, para encadenar llamadas.
84
+ *
85
+ * @example
86
+ * logger.scope('HTTP').badges(['OUTBOUND', 'CACHED']).info('Cache hit');
87
+ * // salida: [HTTP] [OUTBOUND] [CACHED] Cache hit
88
+ *
89
+ * @see {@link badge} para añadir sin reemplazar los existentes.
90
+ * @see {@link clearBadges} para vaciar la lista.
91
+ */
92
+ badges(badges) {
93
+ this.badgeList = [...badges];
94
+ return this;
95
+ }
96
+ /**
97
+ * Añade un badge al scope de forma idempotente (no lo duplica si ya existe).
98
+ *
99
+ * @param {string} badge - Etiqueta a añadir a la lista de badges.
100
+ * @returns {this} La misma instancia, para encadenar llamadas.
101
+ *
102
+ * @example
103
+ * logger.scope('API')
104
+ * .badge('OUTBOUND')
105
+ * .badge('RETRY')
106
+ * .warn('Reintentando');
107
+ * // salida: [API] [OUTBOUND] [RETRY] Reintentando
108
+ */
109
+ badge(badge) {
110
+ if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
111
+ return this;
112
+ }
113
+ /**
114
+ * Vacía la lista de badges del scope.
115
+ *
116
+ * @returns {this} La misma instancia, para encadenar llamadas.
117
+ *
118
+ * @example
119
+ * const http = logger.scope('HTTP');
120
+ * http.badge('OUTBOUND').info('uno');
121
+ * http.clearBadges().info('dos');
122
+ * // [HTTP] [OUTBOUND] uno / [HTTP] dos
123
+ */
124
+ clearBadges() {
125
+ this.badgeList = [];
126
+ return this;
127
+ }
128
+ /**
129
+ * Aplica un theme preset al logger padre. El preset afecta a toda la
130
+ * instancia raíz (no solo a este scope) porque el style es compartido.
131
+ *
132
+ * @param {string} presetName - Nombre del preset registrado en el StyleManager.
133
+ * @returns {this} La misma instancia, para encadenar llamadas.
134
+ *
135
+ * @example
136
+ * logger.scope('UI').style('cyberpunk').info('neon');
137
+ * @see {@link Logger.setTheme}
138
+ */
139
+ style(presetName) {
140
+ this.parent.setTheme(presetName);
141
+ return this;
142
+ }
143
+ /**
144
+ * Crea un {@link ContextLogger} vinculado a este scope. Los contextos se
145
+ * apilan en el prefijo separados por `:`, permitiendo agrupar bloques de
146
+ * logs relacionados (reintentos, sub-etapas, etc.) sin `console.group`.
147
+ *
148
+ * @param {string} contextName - Nombre del contexto a apilar.
149
+ * @returns {ContextLogger} Handler con `run`, `runAsync`, `start`/`end`.
150
+ *
151
+ * @example
152
+ * const retry = logger.scope('HTTP').context('retry');
153
+ * retry.run(() => logger.warn('Reintentando'));
154
+ * // salida: [HTTP:retry] Reintentando
155
+ * @see {@link ContextLogger}
156
+ */
157
+ context(contextName) {
158
+ return new ContextLogger(this, contextName);
159
+ }
160
+ /**
161
+ * Inicia un timer etiquetado bajo el namespace `<scopeName>:<label>`.
162
+ * El label es local a este scope, así que dos scopes pueden reutilizar el
163
+ * mismo nombre sin colisión.
164
+ *
165
+ * @param {string} label - Identificador del timer.
166
+ *
167
+ * @example
168
+ * const http = logger.scope('HTTP');
169
+ * http.time('request');
170
+ * // ... trabajo ...
171
+ * http.timeEnd('request'); // imprime "Timer: request - 12.34ms"
172
+ * @see {@link timeEnd}
173
+ */
174
+ time(label) {
175
+ this.timers.set(label, {
176
+ label: `${this.scopeName}:${label}`,
177
+ startTime: performance.now()
178
+ });
179
+ }
180
+ /**
181
+ * Detiene un timer previamente iniciado con {@link time} y registra la
182
+ * duración con nivel `success`. Si el label no existe, emite un `warn`
183
+ * y devuelve `undefined`.
184
+ *
185
+ * @param {string} label - Mismo label pasado a {@link time}.
186
+ * @returns {number | undefined} Milisegundos transcurridos, o `undefined`
187
+ * si el timer no estaba registrado.
188
+ *
189
+ * @example
190
+ * const http = logger.scope('HTTP');
191
+ * http.time('fetch');
192
+ * await fetch(url);
193
+ * const ms = http.timeEnd('fetch');
194
+ * if (ms && ms > 1000) http.warn('Latencia alta');
195
+ */
196
+ timeEnd(label) {
197
+ const timer = this.timers.get(label);
198
+ if (!timer) {
199
+ this.warn(`Timer '${label}' not found`);
200
+ return;
201
+ }
202
+ const elapsed = performance.now() - timer.startTime;
203
+ this.timers.delete(label);
204
+ this.success(`Timer: ${label} - ${elapsed.toFixed(2)}ms`);
205
+ return elapsed;
206
+ }
207
+ /**
208
+ * Emite un mensaje a nivel `debug` con los bindings actuales del scope.
209
+ *
210
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales (objetos,
211
+ * errores, etc.) serializados igual que en el logger raíz.
212
+ *
213
+ * @example
214
+ * logger.scope('DB').debug('query', { sql, params });
215
+ */
216
+ debug(...args) {
217
+ this.parent.logWithBindings(this.getBindings(), "debug", ...args);
218
+ }
219
+ /**
220
+ * Emite un mensaje a nivel `info` con los bindings actuales del scope.
221
+ *
222
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
223
+ *
224
+ * @example
225
+ * logger.scope('AUTH').info('Login exitoso', { userId });
226
+ */
227
+ info(...args) {
228
+ this.parent.logWithBindings(this.getBindings(), "info", ...args);
229
+ }
230
+ /**
231
+ * Emite un mensaje a nivel `warn` con los bindings actuales del scope.
232
+ *
233
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
234
+ *
235
+ * @example
236
+ * logger.scope('CACHE').warn('Cache miss', { key });
237
+ */
238
+ warn(...args) {
239
+ this.parent.logWithBindings(this.getBindings(), "warn", ...args);
240
+ }
241
+ /**
242
+ * Emite un mensaje a nivel `error` con los bindings actuales del scope.
243
+ *
244
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales (típicamente
245
+ * un `Error` o contexto del fallo).
246
+ *
247
+ * @example
248
+ * logger.scope('DB').error('Conexión rechazada', err);
249
+ */
250
+ error(...args) {
251
+ this.parent.logWithBindings(this.getBindings(), "error", ...args);
252
+ }
253
+ /**
254
+ * Emite un mensaje con badge visual `SUCCESS` a nivel `info`. Úselo para
255
+ * hitos positivos dentro del scope (conexión establecida, sync completo,
256
+ * commit aplicado).
257
+ *
258
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
259
+ *
260
+ * @example
261
+ * logger.scope('SYNC').success('Sincronización completa', { count: 42 });
262
+ */
263
+ success(...args) {
264
+ const bindings = this.getBindings();
265
+ this.parent.logWithBindingsAndTag(bindings, "info", "success", ...args);
266
+ }
267
+ /**
268
+ * Emite un mensaje a nivel `critical` con los bindings actuales del scope.
269
+ * Reservado para fallos que detienen el flujo de la aplicación.
270
+ *
271
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
272
+ *
273
+ * @example
274
+ * logger.scope('PAY').critical('Pasarela inaccesible', err);
275
+ */
276
+ critical(...args) {
277
+ this.parent.logWithBindings(this.getBindings(), "critical", ...args);
278
+ }
279
+ /**
280
+ * Emite un mensaje a nivel `trace` (verbosidad máxima) con los bindings
281
+ * actuales del scope. Solo aparece si la verbosity global lo permite.
282
+ *
283
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
284
+ *
285
+ * @example
286
+ * logger.scope('NET').trace('packet', { bytes });
287
+ */
288
+ trace(...args) {
289
+ this.parent.logWithBindings(this.getBindings(), "trace", ...args);
290
+ }
291
+ /**
292
+ * Delegación a {@link Logger.step}: dibuja una barra de progreso discreta
293
+ * `current/total` para este scope.
294
+ *
295
+ * @param {number} current - Paso actual (1-indexed).
296
+ * @param {number} total - Total de pasos.
297
+ * @param {string} message - Texto mostrado junto al contador.
298
+ * @see {@link Logger.step}
299
+ */
300
+ step(current, total, message) {
301
+ this.parent.step(current, total, message);
302
+ }
303
+ /**
304
+ * Delegación a {@link Logger.header}: imprime un título con separadores visuales.
305
+ *
306
+ * @param {string} title - Texto del título.
307
+ * @param {string} [subtitle] - Subtítulo opcional bajo el título.
308
+ * @see {@link Logger.header}
309
+ */
310
+ header(title, subtitle) {
311
+ this.parent.header(title, subtitle);
312
+ }
313
+ /**
314
+ * Delegación a {@link Logger.divider}: imprime una línea separadora horizontal.
315
+ * @see {@link Logger.divider}
316
+ */
317
+ divider() {
318
+ this.parent.divider();
319
+ }
320
+ /**
321
+ * Delegación a {@link Logger.blank}: inserta una línea en blanco.
322
+ * @see {@link Logger.blank}
323
+ */
324
+ blank() {
325
+ this.parent.blank();
326
+ }
327
+ /**
328
+ * Delegación a {@link Logger.box}: dibuja un recuadro ANSI alrededor de `content`.
329
+ *
330
+ * @param {string} content - Texto a enmarcar.
331
+ * @param {IBoxOptions} [options] - Opciones de estilo del box.
332
+ * @see {@link Logger.box}
333
+ */
334
+ box(content, options) {
335
+ this.parent.box(content, options);
336
+ }
337
+ /**
338
+ * Delegación a {@link Logger.cliTable}: renderiza `rows` como tabla ASCII.
339
+ *
340
+ * @param {Record<string, unknown>[]} rows - Filas a mostrar.
341
+ * @param {ITableOptions} [options] - Opciones de columnas y estilo.
342
+ * @see {@link Logger.cliTable}
343
+ */
344
+ cliTable(rows, options) {
345
+ this.parent.cliTable(rows, options);
346
+ }
347
+ /**
348
+ * Delegación a {@link Logger.spinner}: arranca un spinner con `message`.
349
+ *
350
+ * @param {string} message - Texto a mostrar al lado del spinner.
351
+ * @returns {ISpinnerHandle} Handle para detener/actualizar el spinner.
352
+ * @see {@link Logger.spinner}
353
+ */
354
+ spinner(message) {
355
+ return this.parent.spinner(message);
356
+ }
357
+ /**
358
+ * Delegación a {@link Logger.setCLILevel}: ajusta el nivel mínimo de las
359
+ * primitivas CLI visibles.
360
+ *
361
+ * @param {CLILogLevel} level - Nivel CLI (`silent` … `verbose`).
362
+ * @see {@link Logger.setCLILevel}
363
+ */
364
+ setCLILevel(level) {
365
+ this.parent.setCLILevel(level);
366
+ }
367
+ /**
368
+ * Apila un contexto en el prefijo del scope. Invocado por
369
+ * {@link ContextLogger}; los clientes no deben llamarlo directamente.
370
+ *
371
+ * @param {string} context - Nombre del contexto a apilar.
372
+ * @internal
373
+ */
374
+ _pushContext(context) {
375
+ this.contextStack.push(context);
376
+ }
377
+ /**
378
+ * Desapila el último contexto del prefijo del scope. Invocado por
379
+ * {@link ContextLogger}; los clientes no deben llamarlo directamente.
380
+ *
381
+ * @internal
382
+ */
383
+ _popContext() {
384
+ this.contextStack.pop();
385
+ }
160
386
  };
387
+ /**
388
+ * Logger especializado para llamadas a APIs y servicios externos.
389
+ *
390
+ * Extiende {@link ScopedLogger} pre-seteando el badge `API` y exponiendo
391
+ * atajos para eventos típicos de integración: llamadas lentas ({@link slow}),
392
+ * rate limiting ({@link rateLimit}), fallos de autenticación ({@link auth}) y
393
+ * APIs deprecadas ({@link deprecated}).
394
+ *
395
+ * Se obtiene con `logger.api(name)` y no se construye directamente.
396
+ *
397
+ * @example
398
+ * import logger from '@mks2508/better-logger';
399
+ *
400
+ * const stripe = logger.api('Stripe');
401
+ * stripe.info('Consultando customer', { id });
402
+ * // salida: [API:Stripe] [API] Consultando customer
403
+ *
404
+ * stripe.slow('customer.retrieve', 1250);
405
+ * // salida: [API:Stripe] [API] [SLOW] customer.retrieve (1250ms)
406
+ *
407
+ * @see {@link Logger.api}
408
+ * @see {@link ScopedLogger}
409
+ */
410
+ var APILogger = class extends ScopedLogger {
411
+ /**
412
+ * Construye un APILogger con scope `API:<apiName>` y badge `API` ya aplicado.
413
+ *
414
+ * Los clientes deben usar `logger.api(name)`.
415
+ *
416
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
417
+ * @param {string} apiName - Nombre del servicio/API (se prefija con `API:`).
418
+ */
419
+ constructor(parent, apiName) {
420
+ super(parent, `API:${apiName}`);
421
+ this.badge("API");
422
+ }
423
+ /**
424
+ * Registra una llamada lenta con badge `SLOW` a nivel `warn`.
425
+ *
426
+ * @param {string} message - Descripción de la operación lenta.
427
+ * @param {number} [duration] - Duración medida en ms; si se pasa, se
428
+ * anexa al mensaje como `(Nms)`.
429
+ *
430
+ * @example
431
+ * const t0 = performance.now();
432
+ * await stripe.customers.retrieve(id);
433
+ * logger.api('Stripe').slow('retrieve', performance.now() - t0);
434
+ */
435
+ slow(message, duration) {
436
+ this.badge("SLOW");
437
+ const msg = duration ? `${message} (${duration}ms)` : message;
438
+ this.warn(msg);
439
+ }
440
+ /**
441
+ * Registra un evento de rate limiting (HTTP 429) con badge `RATE_LIMIT`.
442
+ *
443
+ * @param {string} message - Detalle del límite golpeado.
444
+ *
445
+ * @example
446
+ * logger.api('GitHub').rateLimit('Secondary rate limit on /search');
447
+ */
448
+ rateLimit(message) {
449
+ this.badge("RATE_LIMIT");
450
+ this.warn(message);
451
+ }
452
+ /**
453
+ * Registra un fallo de autenticación (401/403) con badge `AUTH` a nivel
454
+ * `error`.
455
+ *
456
+ * @param {string} message - Detalle del fallo de credenciales/token.
457
+ *
458
+ * @example
459
+ * logger.api('OAuth').auth('Token expirado');
460
+ */
461
+ auth(message) {
462
+ this.badge("AUTH");
463
+ this.error(message);
464
+ }
465
+ /**
466
+ * Marca una API como deprecada con badge `DEPRECATED` a nivel `warn`.
467
+ *
468
+ * @param {string} message - Mensaje guiando a la migración (endpoint
469
+ * alternativo, versión retirada, etc.).
470
+ *
471
+ * @example
472
+ * logger.api('Legacy').deprecated('Usar v3; v2 se retira en Q4');
473
+ */
474
+ deprecated(message) {
475
+ this.badge("DEPRECATED");
476
+ this.warn(message);
477
+ }
478
+ };
479
+ /**
480
+ * Logger para componentes UI, módulos o cualquier unidad con ciclo de vida.
481
+ *
482
+ * Extiende {@link ScopedLogger} pre-seteando el badge `COMPONENT` y exponiendo
483
+ * atajos para eventos típicos: {@link lifecycle}, {@link stateChange} y
484
+ * {@link propsChange}.
485
+ *
486
+ * Se obtiene con `logger.component(name)` y no se construye directamente.
487
+ *
488
+ * @example
489
+ * import logger from '@mks2508/better-logger';
490
+ *
491
+ * const cart = logger.component('Cart');
492
+ * cart.lifecycle('mount');
493
+ * // salida: [Cart] [COMPONENT] [LIFECYCLE] mount
494
+ *
495
+ * cart.stateChange('empty', 'has-items', { count: 3 });
496
+ * // salida: [Cart] [COMPONENT] [STATE] empty → has-items { count: 3 }
497
+ *
498
+ * @see {@link Logger.component}
499
+ * @see {@link ScopedLogger}
500
+ */
501
+ var ComponentLogger = class extends ScopedLogger {
502
+ /**
503
+ * Construye un ComponentLogger con badge `COMPONENT` ya aplicado.
504
+ *
505
+ * Los clientes deben usar `logger.component(name)`.
506
+ *
507
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
508
+ * @param {string} componentName - Nombre del componente (scope label).
509
+ */
510
+ constructor(parent, componentName) {
511
+ super(parent, componentName);
512
+ this.badge("COMPONENT");
513
+ }
514
+ /**
515
+ * Registra un evento de ciclo de vida con badge `LIFECYCLE` a nivel `info`.
516
+ *
517
+ * @param {string} event - Nombre del evento (`mount`, `unmount`,
518
+ * `update`, ...).
519
+ * @param {string} [message] - Detalle opcional; si se omite, solo se
520
+ * registra el nombre del evento.
521
+ *
522
+ * @example
523
+ * logger.component('Cart').lifecycle('mount', 'Modal abierto');
524
+ */
525
+ lifecycle(event, message) {
526
+ this.badge("LIFECYCLE");
527
+ const msg = message ? `${event}: ${message}` : event;
528
+ this.info(msg);
529
+ }
530
+ /**
531
+ * Registra una transición de estado con badge `STATE` a nivel `info`.
532
+ *
533
+ * @param {string} from - Estado previo.
534
+ * @param {string} to - Estado nuevo.
535
+ * @param {unknown} [data] - Payload opcional asociado a la transición.
536
+ *
537
+ * @example
538
+ * const fsm = logger.component('FSM');
539
+ * fsm.stateChange('idle', 'loading');
540
+ * fsm.stateChange('loading', 'success', { items: 3 });
541
+ */
542
+ stateChange(from, to, data) {
543
+ this.badge("STATE");
544
+ const msg = `${from} → ${to}`;
545
+ if (data) this.info(msg, data);
546
+ else this.info(msg);
547
+ }
548
+ /**
549
+ * Registra cambios de props/debug del componente con badge `PROPS` a nivel
550
+ * `debug`.
551
+ *
552
+ * @param {Record<string, unknown>} changes - Mapa prop → valor (típicamente
553
+ * el diff de props entre renders).
554
+ *
555
+ * @example
556
+ * logger.component('Cart').propsChange({ itemCount: 5, currency: 'EUR' });
557
+ */
558
+ propsChange(changes) {
559
+ this.badge("PROPS");
560
+ this.debug("Props changed:", changes);
561
+ }
562
+ };
563
+ /**
564
+ * Handler de contexto apilable sobre un {@link ScopedLogger}.
565
+ *
566
+ * Permite agrupar bloques de logs bajo un sub-prefijo separado por `:`,
567
+ * manteniendo la correlación visual sin necesidad de `console.group`. El
568
+ * prefijo compuesto se forma como `<scopeName>:<contextName>`.
569
+ *
570
+ * Se crea con `scopedLogger.context(name)`. El patrón idiomático es
571
+ * {@link run}/{@link runAsync} (auto push/pop con try/finally); {@link start}
572
+ * y {@link end} permiten control manual cuando el bloque no cierra
573
+ * léxicamente (event handlers distribuidos, promesas de larga duración).
574
+ *
575
+ * @example
576
+ * import logger from '@mks2508/better-logger';
577
+ *
578
+ * const http = logger.scope('HTTP');
579
+ *
580
+ * // Bloque síncrono auto-cerrado
581
+ * http.context('retry').run(() => {
582
+ * http.warn('Reintentando petición');
583
+ * });
584
+ * // salida: [HTTP:retry] Reintentando petición
585
+ *
586
+ * // Bloque async auto-cerrado
587
+ * await http.context('refresh').runAsync(async () => {
588
+ * await refreshToken();
589
+ * http.info('Token refrescado');
590
+ * });
591
+ *
592
+ * @see {@link ScopedLogger.context}
593
+ */
594
+ var ContextLogger = class {
595
+ parentLogger;
596
+ contextName;
597
+ /**
598
+ * @param {ScopedLogger} parentLogger - Scope sobre el que se apila el contexto.
599
+ * @param {string} contextName - Sub-prefijo a apilar en el scope padre.
600
+ */
601
+ constructor(parentLogger, contextName) {
602
+ this.parentLogger = parentLogger;
603
+ this.contextName = contextName;
604
+ }
605
+ /**
606
+ * Ejecuta `fn` síncrona dentro del contexto, garantizando el pop del
607
+ * prefijo incluso si `fn` lanza. El contexto solo está activo durante la
608
+ * ejecución de `fn`.
609
+ *
610
+ * @typeParam T - Tipo de retorno de `fn`.
611
+ * @param {() => T} fn - Función a ejecutar bajo el contexto.
612
+ * @returns {T} Lo que devuelva `fn`.
613
+ * @throws {unknown} Relanza cualquier excepción de `fn` tras desapilar.
614
+ *
615
+ * @example
616
+ * logger.scope('HTTP').context('warmup').run(() => {
617
+ * logger.info('Pre-cargando caché');
618
+ * });
619
+ */
620
+ run(fn) {
621
+ this.parentLogger._pushContext(this.contextName);
622
+ try {
623
+ return fn();
624
+ } finally {
625
+ this.parentLogger._popContext();
626
+ }
627
+ }
628
+ /**
629
+ * Variante async de {@link run}: mantiene el contexto activo mientras se
630
+ * awaiting la promesa de `fn`, incluyendo awaits internos.
631
+ *
632
+ * @typeParam T - Tipo resuelto por la promesa de `fn`.
633
+ * @param {() => Promise<T>} fn - Función async a ejecutar bajo el contexto.
634
+ * @returns {Promise<T>} Promesa que resuelve al valor de `fn`.
635
+ * @throws {unknown} Relanza cualquier rechazo de `fn` tras desapilar.
636
+ *
637
+ * @example
638
+ * await logger.scope('HTTP').context('fetch').runAsync(async () => {
639
+ * const r = await fetch(url);
640
+ * logger.info('Recibido', { status: r.status });
641
+ * });
642
+ */
643
+ async runAsync(fn) {
644
+ this.parentLogger._pushContext(this.contextName);
645
+ try {
646
+ return await fn();
647
+ } finally {
648
+ this.parentLogger._popContext();
649
+ }
650
+ }
651
+ /**
652
+ * Apila el contexto manualmente. Útil cuando el bloque que lo consume no
653
+ * cierra léxicamente (event handlers, timeouts, streams). Debe emparejarse
654
+ * con un {@link end} posterior; olvidarlo deja el prefijo contaminado para
655
+ * los logs siguientes del scope.
656
+ *
657
+ * @example
658
+ * const ctx = logger.scope('WS').context('subscribe');
659
+ * socket.onopen = () => { ctx.start(); ctx.info('connected'); };
660
+ * socket.onclose = () => { ctx.info('disconnected'); ctx.end(); };
661
+ * @see {@link end}
662
+ */
663
+ start() {
664
+ this.parentLogger._pushContext(this.contextName);
665
+ }
666
+ /**
667
+ * Desapila el último contexto abierto con {@link start}.
668
+ *
669
+ * @see {@link start}
670
+ */
671
+ end() {
672
+ this.parentLogger._popContext();
673
+ }
674
+ /**
675
+ * Atajo a `scopedLogger.debug(...)`. El contexto se aplica al prefijo del
676
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
677
+ *
678
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
679
+ */
680
+ debug(...args) {
681
+ this.parentLogger.debug(...args);
682
+ }
683
+ /**
684
+ * Atajo a `scopedLogger.info(...)`. El contexto se aplica al prefijo del
685
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
686
+ *
687
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
688
+ */
689
+ info(...args) {
690
+ this.parentLogger.info(...args);
691
+ }
692
+ /**
693
+ * Atajo a `scopedLogger.warn(...)`. El contexto se aplica al prefijo del
694
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
695
+ *
696
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
697
+ */
698
+ warn(...args) {
699
+ this.parentLogger.warn(...args);
700
+ }
701
+ /**
702
+ * Atajo a `scopedLogger.error(...)`. El contexto se aplica al prefijo del
703
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
704
+ *
705
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
706
+ */
707
+ error(...args) {
708
+ this.parentLogger.error(...args);
709
+ }
710
+ /**
711
+ * Atajo a `scopedLogger.success(...)`. El contexto se aplica al prefijo del
712
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
713
+ *
714
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
715
+ */
716
+ success(...args) {
717
+ this.parentLogger.success(...args);
718
+ }
719
+ /**
720
+ * Atajo a `scopedLogger.critical(...)`. El contexto se aplica al prefijo
721
+ * del scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
722
+ *
723
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
724
+ */
725
+ critical(...args) {
726
+ this.parentLogger.critical(...args);
727
+ }
728
+ };
729
+ //#endregion
730
+ //#region src/cli/CommandProcessor.ts
731
+ /**
732
+ * Procesador central del CLI del logger. Resuelve nombres de comando (con
733
+ * aliases), despacha ejecución, mantiene historial acotado (max 100 entradas)
734
+ * y soporta un sistema de plugins para extensión de terceros.
735
+ *
736
+ * No es un binario standalone: se invoca desde la consola del navegador vía
737
+ * `window.cli("<command>")` (modo interactivo habilitado por
738
+ * {@link enterInteractiveMode}) o desde código vía `logger.cli()`. El
739
+ * constructor no registra ningún comando por defecto — usar
740
+ * {@link createDefaultCLI} para obtener una instancia con los 8 comandos
741
+ * estándar ya cargados.
742
+ *
743
+ * @example
744
+ * ```ts
745
+ * const cli = createDefaultCLI();
746
+ * await cli.processCommand('/themes', logger);
747
+ * await cli.processCommand('/config theme=neon', logger);
748
+ * ```
749
+ *
750
+ * @example
751
+ * ```ts
752
+ * // Modo interactivo: expone `window.cli` en el navegador
753
+ * cli.enterInteractiveMode(logger);
754
+ * // Desde la devtools: cli('help') → procesa '/help'
755
+ * ```
756
+ *
757
+ * @see {@link createDefaultCLI}
758
+ * @see {@link ICommand}
759
+ * @see {@link ICLIPlugin}
760
+ */
761
+ var CommandProcessor = class {
762
+ commands = /* @__PURE__ */ new Map();
763
+ aliases = /* @__PURE__ */ new Map();
764
+ plugins = /* @__PURE__ */ new Map();
765
+ history = [];
766
+ maxHistorySize = 100;
767
+ isInteractiveMode = false;
768
+ /**
769
+ * Registra un comando. Si el comando declara `aliases`, también se indexan
770
+ * para resolución. Un comando con el mismo `name` sobreescribe al previo.
771
+ *
772
+ * @param {ICommand} command - Comando a registrar.
773
+ * @see {@link ICommand}
774
+ */
775
+ registerCommand(command) {
776
+ this.commands.set(command.name, command);
777
+ if (command.aliases) for (const alias of command.aliases) this.aliases.set(alias, command.name);
778
+ }
779
+ /**
780
+ * Registra un plugin: indexa todos sus commands y, si el plugin define
781
+ * `initialize`, lo invoca con el processor y el logger. Los comandos del
782
+ * plugin se registran vía {@link registerCommand} y sus aliases quedan
783
+ * resolvibles igual que los directos.
784
+ *
785
+ * @param {ICLIPlugin} plugin - Plugin a registrar.
786
+ * @param {Logger} [logger] - Logger activo; requerido solo si el plugin define `initialize`.
787
+ * @throws {Error} Si ya existe un plugin registrado con el mismo `name`.
788
+ * @see {@link unregisterPlugin}
789
+ */
790
+ registerPlugin(plugin, logger) {
791
+ if (this.plugins.has(plugin.name)) throw new Error(`Plugin ${plugin.name} is already registered`);
792
+ this.plugins.set(plugin.name, plugin);
793
+ for (const command of plugin.commands) this.registerCommand(command);
794
+ if (plugin.initialize && logger) plugin.initialize(this, logger);
795
+ }
796
+ /**
797
+ * Desregistra un plugin por nombre: elimina todos sus commands (y los
798
+ * aliases que aportasen), invoca su hook `cleanup` si existe y lo quita
799
+ * del registry. No-op si el nombre no existe.
800
+ *
801
+ * @param {string} pluginName - Nombre del plugin a desregistrar.
802
+ * @see {@link registerPlugin}
803
+ */
804
+ unregisterPlugin(pluginName) {
805
+ const plugin = this.plugins.get(pluginName);
806
+ if (!plugin) return;
807
+ for (const command of plugin.commands) {
808
+ this.commands.delete(command.name);
809
+ if (command.aliases) for (const alias of command.aliases) this.aliases.delete(alias);
810
+ }
811
+ if (plugin.cleanup) plugin.cleanup();
812
+ this.plugins.delete(pluginName);
813
+ }
814
+ /**
815
+ * Lista todos los commands registrados (directamente o vía plugins).
816
+ * No incluye aliases.
817
+ *
818
+ * @returns {ICommand[]} Snapshot array de los commands registrados.
819
+ */
820
+ getCommands() {
821
+ return Array.from(this.commands.values());
822
+ }
823
+ /**
824
+ * Resuelve un comando por nombre canónico o alias. Devuelve `undefined`
825
+ * si no existe ninguno que matchee.
826
+ *
827
+ * @param {string} name - Nombre canónico o alias del comando.
828
+ * @returns {ICommand | undefined} El comando resuelto, o `undefined`.
829
+ */
830
+ getCommand(name) {
831
+ let command = this.commands.get(name);
832
+ if (command) return command;
833
+ const aliasTarget = this.aliases.get(name);
834
+ if (aliasTarget) return this.commands.get(aliasTarget);
835
+ }
836
+ /**
837
+ * Devuelve una copia del historial de comandos ejecutados (más recientes
838
+ * primero). Acotado a 100 entradas por {@link maxHistorySize}; las más
839
+ * viejas se descartan al insertar nuevas.
840
+ *
841
+ * @returns {HistoryEntry[]} Snapshot del historial; mutar el array devuelto
842
+ * no afecta al estado interno del processor.
843
+ */
844
+ getHistory() {
845
+ return [...this.history];
846
+ }
847
+ /**
848
+ * Vacía el historial de comandos en memoria.
849
+ */
850
+ clearHistory() {
851
+ this.history = [];
852
+ }
853
+ /**
854
+ * Lista los plugins actualmente registrados.
855
+ *
856
+ * @returns {ICLIPlugin[]} Snapshot array de plugins activos.
857
+ */
858
+ getPlugins() {
859
+ return Array.from(this.plugins.values());
860
+ }
861
+ /**
862
+ * Activa el modo interactivo. Marca el flag interno y, si se ejecuta en
863
+ * navegador, expone `window.cli(command)` para invocar comandos desde la
864
+ * devtools sin prefijo `/` (se añade automáticamente al input).
865
+ *
866
+ * @param {Logger} logger - Logger activo (emite el mensaje de bienvenida
867
+ * con hint sobre `cli(...)` en browser).
868
+ * @see {@link exitInteractiveMode}
869
+ */
870
+ enterInteractiveMode(logger) {
871
+ this.isInteractiveMode = true;
872
+ logger.info("🔧 Interactive CLI mode activated. Type /exit to quit, /help for commands.");
873
+ if (typeof window !== "undefined") this.setupBrowserInteractiveMode(logger);
874
+ }
875
+ /**
876
+ * Desactiva el flag de modo interactivo. Nota: no elimina el `window.cli`
877
+ * que {@link enterInteractiveMode} haya expuesto en el navegador — el
878
+ * handler global sigue vivo hasta reload.
879
+ *
880
+ * @see {@link enterInteractiveMode}
881
+ */
882
+ exitInteractiveMode() {
883
+ this.isInteractiveMode = false;
884
+ }
885
+ /**
886
+ * Instala `window.cli(command)` como wrapper delgado alrededor de
887
+ * {@link processCommand}, prefijando `/` automáticamente. Solo se invoca
888
+ * desde {@link enterInteractiveMode} cuando `window` está disponible.
889
+ *
890
+ * @internal
891
+ * @param logger - Logger activo, reenviado a cada invocación.
892
+ */
893
+ setupBrowserInteractiveMode(logger) {
894
+ window.cli = (commandString) => {
895
+ return this.processCommand(`/${commandString}`, logger);
896
+ };
897
+ logger.info("💡 Use cli(\"command\") to execute CLI commands in browser console.");
898
+ }
899
+ /**
900
+ * Parsea y ejecuta un comando. El formato esperado es `/name args...`:
901
+ * split por espacios, primer token = nombre del comando, resto = args
902
+ * (re-joined con espacios). Si el comando no existe, loguea el error y
903
+ * sugiere similares vía {@link getSuggestions} ("Did you mean: ...?").
904
+ *
905
+ * Toda invocación (válida o no) se registra en el historial con flag de
906
+ * éxito/fallo según si `execute` resolvió o throweó.
907
+ *
908
+ * @param {string} commandString - Comando completo, debe empezar con `/`.
909
+ * @param {Logger} logger - Logger activo para output y errores.
910
+ * @returns {Promise<void>} Resuelve cuando el comando termina (sync o async).
911
+ * Nunca rechaza: los errores de `execute` se capturan y se loguean.
912
+ * @see {@link ICommand.execute}
913
+ * @see {@link getSuggestions}
914
+ */
915
+ async processCommand(commandString, logger) {
916
+ if (!commandString.startsWith("/")) {
917
+ logger.error("Invalid command. Commands must start with /");
918
+ this.addToHistory(commandString, false);
919
+ return;
920
+ }
921
+ const parts = commandString.slice(1).split(" ");
922
+ const commandName = parts[0] || "";
923
+ const args = parts.slice(1).join(" ");
924
+ const command = this.getCommand(commandName);
925
+ if (!command) {
926
+ logger.error(`Unknown command: ${commandName}. Type /help for available commands.`);
927
+ const suggestions = this.getSuggestions(commandName);
928
+ if (suggestions.length > 0) logger.info(`📋 Did you mean: ${suggestions.slice(0, 3).join(", ")}?`);
929
+ this.addToHistory(commandString, false);
930
+ return;
931
+ }
932
+ try {
933
+ await command.execute(args || "", logger);
934
+ this.addToHistory(commandString, true);
935
+ } catch (error) {
936
+ logger.error(`Command '${commandName}' failed:`, error);
937
+ this.addToHistory(commandString, false);
938
+ }
939
+ }
940
+ /**
941
+ * Inserta una entrada al frente del historial y trunca a
942
+ * {@link maxHistorySize} (100) si hace falta.
943
+ *
944
+ * @internal
945
+ * @param command - String crudo del comando ejecutado.
946
+ * @param success - Si la ejecución tuvo éxito.
947
+ */
948
+ addToHistory(command, success) {
949
+ this.history.unshift({
950
+ command,
951
+ timestamp: /* @__PURE__ */ new Date(),
952
+ success
953
+ });
954
+ if (this.history.length > this.maxHistorySize) this.history = this.history.slice(0, this.maxHistorySize);
955
+ }
956
+ /**
957
+ * Devuelve nombres de comando que empiezan con el prefijo dado. Alimente
958
+ * el hint "Did you mean" de {@link processCommand} cuando un comando no
959
+ * se encuentra. Match por `startsWith` (no fuzzy).
960
+ *
961
+ * @param {string} partial - Prefijo parcial tipeado por el usuario.
962
+ * @returns {string[]} Nombres canónicos que matchean; aliases excluidos.
963
+ */
964
+ getSuggestions(partial) {
965
+ return Array.from(this.commands.keys()).filter((name) => name.startsWith(partial));
966
+ }
967
+ };
968
+ //#endregion
969
+ //#region src/cli/commands/ConfigCommand.ts
970
+ /**
971
+ * Comando `/config` del CLI runtime del {@link Logger}. Inspecciona o muta
972
+ * la configuración del logger en vivo desde la DevTools console.
973
+ *
974
+ * Acepta tres modos de invocación:
975
+ * - Sin argumentos: vuelca el estado actual como tabla agrupada.
976
+ * - JSON completo (empieza con `{`): aplica un objeto de configuración parcial.
977
+ * - Pares `key=value` separados por coma: atajo para mutaciones puntuales.
978
+ *
979
+ * Solo se aplican las keys de la whitelist interna (`theme`, `verbosity`,
980
+ * `enableColors`, `enableTimestamps`, `enableStackTrace`, `globalPrefix`,
981
+ * `bannerType`); cualquier otra key se rechaza con un `warn` y se ignora.
982
+ *
983
+ * @example
984
+ * // Sin argumentos: ver estado actual
985
+ * // > /config
986
+ *
987
+ * @example
988
+ * // Objeto JSON completo
989
+ * // > /config {"theme":"neon","verbosity":"debug"}
990
+ *
991
+ * @example
992
+ * // Atajo key=value (múltiples pares separados por coma)
993
+ * // > /config theme=neon,verbosity=debug,globalPrefix=MiApp
994
+ *
995
+ * @see {@link ICommand} para el contrato que implementa este comando.
996
+ * @see {@link Logger.setTheme}, {@link Logger.setVerbosity},
997
+ * {@link Logger.setBannerType}, {@link Logger.setGlobalPrefix}
998
+ * para los setters subyacentes.
999
+ */
1000
+ var ConfigCommand = class {
1001
+ name = "config";
1002
+ description = "Show or update logger configuration";
1003
+ usage = "/config [json|key=value,...]";
1004
+ /**
1005
+ * Ejecuta el comando `/config` contra el logger dado.
1006
+ *
1007
+ * @param args - Argumentos crudos del usuario. Vacío = status; con `{`
1008
+ * inicial = parse JSON; resto = pares `key=value` separados
1009
+ * por coma.
1010
+ * @param logger - Instancia destino cuyos setters se invocan.
1011
+ */
1012
+ execute(args, logger) {
1013
+ if (!args) {
1014
+ this.showStatus(logger);
1015
+ return;
1016
+ }
1017
+ try {
1018
+ if (args.startsWith("{")) {
1019
+ const config = JSON.parse(args);
1020
+ this.applyConfig(config, logger);
1021
+ } else {
1022
+ const pairs = args.split(",").map((pair) => pair.trim().split("="));
1023
+ const config = {};
1024
+ pairs.forEach(([key, value]) => {
1025
+ if (key && value) config[key.trim()] = value.trim().replace(/["']/g, "");
1026
+ });
1027
+ this.applyConfig(config, logger);
1028
+ }
1029
+ } catch (error) {
1030
+ logger.error("Invalid config format. Use JSON or key=value pairs:", error);
1031
+ logger.info("Examples: /config {\"theme\":\"dark\"} or /config theme=neon,verbosity=debug");
1032
+ }
1033
+ }
1034
+ showStatus(logger) {
1035
+ const statusData = {
1036
+ theme: logger.getConfig().theme || "default",
1037
+ verbosity: logger.getConfig().verbosity,
1038
+ colors: logger.getConfig().enableColors,
1039
+ timestamps: logger.getConfig().enableTimestamps,
1040
+ stackTrace: logger.getConfig().enableStackTrace,
1041
+ globalPrefix: logger.getConfig().globalPrefix || "none",
1042
+ bannerType: logger.getConfig().bannerType || "simple",
1043
+ handlers: logger.getHandlers().length
1044
+ };
1045
+ logger.group("⚙️ Logger Configuration");
1046
+ logger.table(statusData);
1047
+ logger.groupEnd();
1048
+ }
1049
+ applyConfig(config, logger) {
1050
+ const validKeys = [
1051
+ "theme",
1052
+ "verbosity",
1053
+ "enableColors",
1054
+ "enableTimestamps",
1055
+ "enableStackTrace",
1056
+ "globalPrefix",
1057
+ "bannerType"
1058
+ ];
1059
+ const applied = [];
1060
+ Object.entries(config).forEach(([key, value]) => {
1061
+ if (validKeys.includes(key)) if (key === "theme" && typeof value === "string") {
1062
+ logger.setTheme(value);
1063
+ applied.push(`${key}=${value}`);
1064
+ } else if (key === "bannerType" && typeof value === "string") {
1065
+ logger.setBannerType(value);
1066
+ applied.push(`${key}=${value}`);
1067
+ } else if (key === "verbosity") {
1068
+ logger.setVerbosity(value);
1069
+ applied.push(`${key}=${value}`);
1070
+ } else if (key === "globalPrefix") {
1071
+ logger.setGlobalPrefix(value);
1072
+ applied.push(`${key}=${value}`);
1073
+ } else {
1074
+ logger.updateConfig({ [key]: value });
1075
+ applied.push(`${key}=${value}`);
1076
+ }
1077
+ else logger.warn(`Invalid config key: ${key}`);
1078
+ });
1079
+ if (applied.length > 0) logger.success(`Configuration updated: ${applied.join(", ")}`);
1080
+ }
1081
+ };
1082
+ //#endregion
1083
+ //#region src/cli/commands/ThemeCommand.ts
1084
+ /**
1085
+ * Comando `/themes` del CLI runtime del {@link Logger}. Lista los presets
1086
+ * temáticos disponibles en {@link THEME_PRESETS}, renderizando una preview
1087
+ * con los colores reales de cada tema (background, foreground, border).
1088
+ *
1089
+ * Es de solo lectura: no muta el logger. Útil para descubrir qué tema
1090
+ * aplicar antes de correr `/config theme=<name>`.
1091
+ *
1092
+ * @example
1093
+ * // Listar todos los temas con preview coloreada
1094
+ * // > /themes
1095
+ *
1096
+ * @see {@link THEME_PRESETS} para el catálogo completo de temas.
1097
+ * @see {@link ConfigCommand} para aplicar un tema vía `/config theme=...`.
1098
+ */
1099
+ var ThemesCommand = class {
1100
+ name = "themes";
1101
+ description = "Show available theme presets";
1102
+ usage = "/themes";
1103
+ /**
1104
+ * Ejecuta el comando `/themes` contra el logger dado.
1105
+ *
1106
+ * @param _args - Ignorado (comando sin parámetros).
1107
+ * @param logger - Instancia usada para abrir/cerrar el `group` de salida.
1108
+ */
1109
+ execute(_args, logger) {
1110
+ logger.group("🎨 Available Themes");
1111
+ Object.keys(THEME_PRESETS).forEach((themeName) => {
1112
+ const preview = THEME_PRESETS[themeName];
1113
+ const previewStyle = new StyleBuilder().bg(preview.info.background).color(preview.info.color).padding("4px 8px").rounded("4px").border(preview.info.border).build();
1114
+ console.log(`%c${themeName}`, previewStyle, `- ${themeName} theme preview`);
1115
+ });
1116
+ logger.groupEnd();
1117
+ }
1118
+ };
1119
+ /**
1120
+ * Comando `/banners` del CLI runtime del {@link Logger}. Enumera los tipos
1121
+ * de banner disponibles en {@link BANNER_VARIANTS} (`simple`, `ascii`,
1122
+ * `unicode`, ...) con una mini-preview de cada uno para inspección visual.
1123
+ *
1124
+ * Es de solo lectura: no muta el logger. Para cambiar el banner activo
1125
+ * usar {@link BannerCommand}.
1126
+ *
1127
+ * @example
1128
+ * // Listar todas las variantes de banner con preview
1129
+ * // > /banners
1130
+ *
1131
+ * @see {@link BANNER_VARIANTS} para el catálogo completo de variantes.
1132
+ * @see {@link BannerCommand} para aplicar un tipo concreto.
1133
+ */
1134
+ var BannersCommand = class {
1135
+ name = "banners";
1136
+ description = "Show available banner types";
1137
+ usage = "/banners";
1138
+ /**
1139
+ * Ejecuta el comando `/banners` contra el logger dado.
1140
+ *
1141
+ * @param _args - Ignorado (comando sin parámetros).
1142
+ * @param logger - Instancia usada para abrir/cerrar el `group` de salida.
1143
+ */
1144
+ execute(_args, logger) {
1145
+ logger.group("🖼️ Available Banner Types");
1146
+ Object.keys(BANNER_VARIANTS).forEach((bannerName) => {
1147
+ const banner = BANNER_VARIANTS[bannerName];
1148
+ console.log(`%c${bannerName}`, "font-weight: bold; color: #667eea;");
1149
+ console.log(`%cPreview:`, "color: #666; font-size: 12px;");
1150
+ if (bannerName === "simple") console.log(`%c${banner.text}`, banner.style);
1151
+ else if (bannerName === "ascii") console.log(`%c${banner.text.split("\n").slice(1, 4).join("\n")}...`, "font-family: monospace; color: #667eea; font-size: 10px;");
1152
+ else if (bannerName === "unicode") console.log(`%c${banner.text}`, banner.style);
1153
+ else console.log(`%c${bannerName} banner`, "color: #666; font-style: italic;");
1154
+ });
1155
+ logger.groupEnd();
1156
+ }
1157
+ };
1158
+ /**
1159
+ * Comando `/banner [type]` del CLI runtime del {@link Logger}.
1160
+ *
1161
+ * - Sin argumentos: re-renderiza el banner actualmente activo.
1162
+ * - Con un tipo válido: lo aplica vía {@link Logger.setBannerType} y lo
1163
+ * muestra inmediatamente.
1164
+ * - Con un tipo inválido: loguea un `error` listando las opciones válidas.
1165
+ *
1166
+ * @example
1167
+ * // Mostrar el banner actual
1168
+ * // > /banner
1169
+ *
1170
+ * @example
1171
+ * // Cambiar a un tipo concreto
1172
+ * // > /banner ascii
1173
+ *
1174
+ * @see {@link BANNER_VARIANTS} para los tipos aceptados.
1175
+ * @see {@link Logger.setBannerType} y {@link Logger.showBanner} para los
1176
+ * métodos subyacentes.
1177
+ */
1178
+ var BannerCommand = class {
1179
+ name = "banner";
1180
+ description = "Change or show current banner type";
1181
+ usage = "/banner [type]";
1182
+ /**
1183
+ * Ejecuta el comando `/banner` contra el logger dado.
1184
+ *
1185
+ * @param args - Tipo de banner solicitado. Vacío = mostrar banner actual.
1186
+ * @param logger - Instancia destino cuyo banner se actualiza/muestra.
1187
+ */
1188
+ execute(args, logger) {
1189
+ if (!args) {
1190
+ logger.showBanner();
1191
+ return;
1192
+ }
1193
+ if (args in BANNER_VARIANTS) {
1194
+ logger.setBannerType(args);
1195
+ logger.showBanner();
1196
+ } else logger.error(`Invalid banner type: ${args}. Available: ${Object.keys(BANNER_VARIANTS).join(", ")}`);
1197
+ }
1198
+ };
1199
+ //#endregion
1200
+ //#region src/cli/commands/ExportCommand.ts
1201
+ /**
1202
+ * Comando `/status` del CLI runtime del {@link Logger}. Vuelca la
1203
+ * configuración vigente y algunas estadísticas (theme, verbosity, flags
1204
+ * de features, handler count, bufferSize) en una tabla agrupada dentro
1205
+ * de la consola. Es de solo lectura: no muta el logger.
1206
+ *
1207
+ * @example
1208
+ * // Inspeccionar el estado actual del logger
1209
+ * // > /status
1210
+ *
1211
+ * @see {@link Logger.getConfig} fuente de los datos mostrados.
1212
+ */
1213
+ var StatusCommand = class {
1214
+ name = "status";
1215
+ description = "Show current logger status and configuration";
1216
+ usage = "/status";
1217
+ /**
1218
+ * Ejecuta el comando `/status` contra el logger dado.
1219
+ *
1220
+ * @param _args - Ignorado (comando sin parámetros).
1221
+ * @param logger - Instancia de la que se lee la configuración.
1222
+ */
1223
+ execute(_args, logger) {
1224
+ const config = logger.getConfig();
1225
+ const statusData = {
1226
+ theme: config.theme ? config.theme : "default",
1227
+ verbosity: config.verbosity,
1228
+ colors: config.enableColors,
1229
+ timestamps: config.enableTimestamps,
1230
+ stackTrace: config.enableStackTrace,
1231
+ globalPrefix: config.globalPrefix ? config.globalPrefix : "none",
1232
+ bannerType: config.bannerType ? config.bannerType : "simple",
1233
+ handlers: logger.getHandlers().length,
1234
+ bufferSize: config.bufferSize ? config.bufferSize : 1e3
1235
+ };
1236
+ logger.group("⚙️ Logger Configuration");
1237
+ logger.table(statusData);
1238
+ logger.groupEnd();
1239
+ }
1240
+ };
1241
+ /**
1242
+ * Comando `/reset` del CLI runtime del {@link Logger}. Restaura la
1243
+ * configuración a sus defaults de fábrica vía {@link Logger.resetConfig}.
1244
+ * No resetea handlers ni transports registrados — solo config.
1245
+ *
1246
+ * @example
1247
+ * // Volver a la configuración por defecto
1248
+ * // > /reset
1249
+ *
1250
+ * @see {@link Logger.resetConfig} para el método subyacente.
1251
+ */
1252
+ var ResetCommand = class {
1253
+ name = "reset";
1254
+ description = "Reset logger configuration to defaults";
1255
+ usage = "/reset";
1256
+ /**
1257
+ * Ejecuta el comando `/reset` contra el logger dado.
1258
+ *
1259
+ * @param _args - Ignorado (comando sin parámetros).
1260
+ * @param logger - Instancia cuya configuración se resetea.
1261
+ */
1262
+ execute(_args, logger) {
1263
+ logger.resetConfig();
1264
+ }
1265
+ };
1266
+ /**
1267
+ * Comando `/demo` del CLI runtime del {@link Logger}. Ejecuta una
1268
+ * demostración integral de las capacidades del logger: todos los niveles
1269
+ * de log (debug → critical), tablas, timers (`time`/`timeEnd`), SVG inline
1270
+ * y mensajes animados. Útil para validar que el styling funciona en un
1271
+ * entorno nuevo o tras un cambio de tema.
1272
+ *
1273
+ * @example
1274
+ * // Lanzar la demo completa
1275
+ * // > /demo
1276
+ *
1277
+ * @see {@link Logger} para cada feature individual (`table`, `time`,
1278
+ * `logWithSVG`, `logAnimated`, ...).
1279
+ */
1280
+ var DemoCommand = class {
1281
+ name = "demo";
1282
+ description = "Show comprehensive feature demonstration";
1283
+ usage = "/demo";
1284
+ /**
1285
+ * Ejecuta el comando `/demo` contra el logger dado.
1286
+ *
1287
+ * @param _args - Ignorado (comando sin parámetros).
1288
+ * @param logger - Instancia sobre la que se ejecutan los ejemplos.
1289
+ */
1290
+ execute(_args, logger) {
1291
+ logger.group("🎪 Advanced Logger Demo");
1292
+ logger.debug("Debug message with detailed information");
1293
+ logger.info("Informational message about system state");
1294
+ logger.warn("Warning about deprecated feature");
1295
+ logger.error("Error processing user request");
1296
+ logger.success("Operation completed successfully");
1297
+ logger.critical("Critical system failure detected");
1298
+ logger.group("📊 Advanced Features Demo");
1299
+ logger.table([
1300
+ {
1301
+ feature: "Styled Console",
1302
+ status: "✅ Active",
1303
+ performance: "Excellent"
1304
+ },
1305
+ {
1306
+ feature: "Theme System",
1307
+ status: "✅ Active",
1308
+ performance: "Great"
1309
+ },
1310
+ {
1311
+ feature: "CLI Interface",
1312
+ status: "✅ Active",
1313
+ performance: "Good"
1314
+ },
1315
+ {
1316
+ feature: "Export System",
1317
+ status: "✅ Active",
1318
+ performance: "Excellent"
1319
+ }
1320
+ ]);
1321
+ logger.time("demo-operation");
1322
+ setTimeout(() => {
1323
+ logger.timeEnd("demo-operation");
1324
+ }, 100);
1325
+ logger.logWithSVG("SVG Demo");
1326
+ logger.logAnimated("🌟 Animated Logger Demo 🌟", 2);
1327
+ logger.groupEnd();
1328
+ logger.groupEnd();
1329
+ logger.info("Demo completed! Check the console for styled output.");
1330
+ }
1331
+ };
1332
+ //#endregion
1333
+ //#region src/cli/help.ts
1334
+ /**
1335
+ * Comando `/help`: renderiza en consola el panel de ayuda del CLI con todos
1336
+ * los comandos disponibles, opciones de configuración, filtros de export y
1337
+ * ejemplos. El panel usa un gradient claro con {@link StyleBuilder} y los
1338
+ * quick tips se agrupan vía `logger.group`.
1339
+ *
1340
+ * Registrado por defecto por {@link createDefaultCLI}.
1341
+ *
1342
+ * @example
1343
+ * ```ts
1344
+ * const cli = createDefaultCLI();
1345
+ * await cli.processCommand('/help', logger);
1346
+ * // Imprime el panel ASCII con gradient + grupo "Quick Tips".
1347
+ * ```
1348
+ *
1349
+ * @see {@link ICommand}
1350
+ * @see {@link createDefaultCLI}
1351
+ */
1352
+ var HelpCommand = class {
1353
+ name = "help";
1354
+ description = "Show CLI help and available commands";
1355
+ usage = "/help [command]";
1356
+ /**
1357
+ * Renderiza el panel de ayuda completo. Actualmente ignora `_args`: el
1358
+ * `usage` declara `/help [command]` (sub-comando opcional) pero la
1359
+ * implementación siempre muestra el panel global.
1360
+ *
1361
+ * @param {string} _args - Argumentos opcionales (reservado para ayuda por
1362
+ * sub-comando; sin uso actual).
1363
+ * @param {Logger} logger - Logger activo; se usa solo para `group`/`info`
1364
+ * de los quick tips.
1365
+ * @returns {void}
1366
+ */
1367
+ execute(_args, logger) {
1368
+ 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();
1369
+ console.log(`%c
1370
+ ╭─────────────── ADVANCED LOGGER CLI COMMANDS ─────────────────╮
1371
+ │ │
1372
+ │ CONFIGURATION │
1373
+ │ /config Show current configuration │
1374
+ │ /config {json} Apply JSON configuration │
1375
+ │ /config key=val Apply key-value configuration │
1376
+ │ /themes Show available themes │
1377
+ │ /banners Show available banner types │
1378
+ │ /banner [type] Change/show banner type │
1379
+ │ /status Show logger status & buffer stats │
1380
+ │ /demo Show feature demonstration │
1381
+ │ /reset Reset to default configuration │
1382
+ │ │
1383
+ │ EXPORT & CLIPBOARD │
1384
+ │ /export <format> Export logs (json|csv|md|plain|html) │
1385
+ │ /copy <format> Copy logs to clipboard │
1386
+ │ /buffer-size N Set log buffer size │
1387
+ │ /buffer-info Show buffer statistics │
1388
+ │ /clear-buffer Clear stored logs │
1389
+ │ │
1390
+ │ EXPORT FILTERS (for export/copy commands) │
1391
+ │ --level error,warn Filter by log levels │
1392
+ │ --since 2h Logs from last 2 hours │
1393
+ │ --until 1h Logs until 1 hour ago │
1394
+ │ --prefix API,DB Filter by prefixes │
1395
+ │ --exclude-prefix INT Exclude prefixes │
1396
+ │ --last 50 Last 50 logs only │
1397
+ │ --first 25 First 25 logs only │
1398
+ │ --search "error" Search in log messages │
1399
+ │ --with-stack Only logs with stack traces │
1400
+ │ --errors-only Only error + critical logs │
1401
+ │ --group-by level Group by level/prefix/hour │
1402
+ │ │
1403
+ │ EXPORT OPTIONS │
1404
+ │ --minimal Minimal output format │
1405
+ │ --compact Remove extra whitespace │
1406
+ │ --styled Include styling (HTML format) │
1407
+ │ │
1408
+ ├──────────────────── CONFIGURATION OPTIONS ─────────────────┤
1409
+ │ │
1410
+ │ theme: default | dark | light | neon | minimal | cyberpunk│
1411
+ │ bannerType: simple | ascii | unicode | svg | animated │
1412
+ │ verbosity: debug | info | warn | error | critical | silent│
1413
+ │ enableColors: true | false │
1414
+ │ enableTimestamps: true | false │
1415
+ │ enableStackTrace: true | false │
1416
+ │ globalPrefix: "string" │
1417
+ │ bufferSize: number (50-10000) │
1418
+ │ │
1419
+ ├──────────────────────── EXAMPLES ──────────────────────────┤
1420
+ │ │
1421
+ │ Basic Configuration: │
1422
+ │ /config {"theme":"dark","verbosity":"debug"} │
1423
+ │ /config theme=neon,bufferSize=2000 │
1424
+ │ /banner animated Change to animated banner │
1425
+ │ │
1426
+ │ Export Examples: │
1427
+ │ /export json --level=error,warn --last=25 │
1428
+ │ /export csv --since=2h --prefix=API │
1429
+ │ /export markdown --group-by=level --errors-only │
1430
+ │ /export html --styled --since=1h │
1431
+ │ │
1432
+ │ Clipboard Examples: │
1433
+ │ /copy plain --minimal --last=10 │
1434
+ │ /copy json --search="authentication" --compact │
1435
+ │ /copy csv --since=30m --exclude-prefix=DEBUG │
1436
+ │ │
1437
+ │ Buffer Management: │
1438
+ │ /buffer-size 5000 Increase buffer to 5000 logs │
1439
+ │ /buffer-info Show detailed buffer statistics │
1440
+ │ /clear-buffer Clear all stored logs │
1441
+ │ │
1442
+ │ Time Formats: │
1443
+ │ --since=2h 2 hours ago │
1444
+ │ --since=30m 30 minutes ago │
1445
+ │ --since=1d 1 day ago │
1446
+ │ --since="2024-01-01T10:00:00Z" Specific ISO date │
1447
+ │ │
1448
+ ╰─────────────────────────────────────────────────────────────╯`, helpStyle);
1449
+ logger.group("💡 Quick Tips");
1450
+ [
1451
+ "Use /demo to see all logger features in action",
1452
+ "Logs are automatically stored in a circular buffer for export",
1453
+ "Export formats: JSON (structured), CSV (Excel), Markdown (readable), Plain (simple), HTML (styled)",
1454
+ "Time filters support relative (2h, 30m) and absolute (ISO) formats",
1455
+ "Combine multiple filters: /export json --level=error --since=1h --search=\"auth\"",
1456
+ "Use /copy for quick clipboard access instead of /export"
1457
+ ].forEach((tip) => {
1458
+ logger.info(`• ${tip}`);
1459
+ });
1460
+ logger.groupEnd();
1461
+ }
1462
+ };
1463
+ //#endregion
1464
+ //#region src/cli/index.ts
1465
+ /**
1466
+ * Crea un {@link CommandProcessor} con los 8 comandos estándar ya registrados:
1467
+ * `help`, `config`, `themes`, `banners`, `banner`, `status`, `reset` y
1468
+ * `demo`. Es el factory canónico — los consumidores normalmente no construyen
1469
+ * un `CommandProcessor` vacío a mano, ya que este no trae comandos cargados.
1470
+ *
1471
+ * @returns {CommandProcessor} Processor listo para usar, sin modo interactivo activo.
1472
+ *
1473
+ * @example
1474
+ * ```ts
1475
+ * const cli = createDefaultCLI();
1476
+ * await cli.processCommand('/help', logger);
1477
+ * await cli.processCommand('/config theme=neon', logger);
1478
+ * ```
1479
+ *
1480
+ * @example
1481
+ * ```ts
1482
+ * // Modo interactivo en el navegador: expone `window.cli`
1483
+ * const cli = createDefaultCLI();
1484
+ * cli.enterInteractiveMode(logger);
1485
+ * // desde devtools: cli('themes') → procesa '/themes'
1486
+ * ```
1487
+ *
1488
+ * @see {@link CommandProcessor}
1489
+ * @see {@link HelpCommand}
1490
+ */
1491
+ function createDefaultCLI() {
1492
+ const processor = new CommandProcessor();
1493
+ processor.registerCommand(new HelpCommand());
1494
+ processor.registerCommand(new ConfigCommand());
1495
+ processor.registerCommand(new ThemesCommand());
1496
+ processor.registerCommand(new BannersCommand());
1497
+ processor.registerCommand(new BannerCommand());
1498
+ processor.registerCommand(new StatusCommand());
1499
+ processor.registerCommand(new ResetCommand());
1500
+ processor.registerCommand(new DemoCommand());
1501
+ return processor;
1502
+ }
1503
+ //#endregion
1504
+ //#region src/transports/TransportBridge.ts
1505
+ /**
1506
+ * Crea una instancia de {@link TransportBridge}.
1507
+ *
1508
+ * @internal
1509
+ */
1510
+ function createTransportBridge() {
1511
+ let transportManager;
1512
+ return {
1513
+ addTransport(target) {
1514
+ if (!transportManager) transportManager = new TransportManager();
1515
+ return transportManager.add(target);
1516
+ },
1517
+ removeTransport(id) {
1518
+ return transportManager?.remove(id) ?? false;
1519
+ },
1520
+ async flushTransports() {
1521
+ await transportManager?.flush();
1522
+ },
1523
+ async closeTransports() {
1524
+ await transportManager?.close();
1525
+ },
1526
+ getTransportManager() {
1527
+ return transportManager;
1528
+ },
1529
+ writeRecord(record) {
1530
+ if (!transportManager) return;
1531
+ transportManager.write(record).catch(() => {});
1532
+ }
1533
+ };
1534
+ }
1535
+ //#endregion
1536
+ //#region src/playground/TerminalBridge.ts
1537
+ /**
1538
+ * Crea un {@link TerminalBridge} usando un getter para evitar referencias
1539
+ * circulares en la construcción.
1540
+ *
1541
+ * @internal
1542
+ */
1543
+ function createTerminalBridge(options) {
1544
+ let _showPrimitives = true;
1545
+ let _serverFallback;
1546
+ return {
1547
+ step(current, total, message) {
1548
+ if (!_showPrimitives) return;
1549
+ if (!isRunningInTerminal()) {
1550
+ this.getServerFallback().step(current, total, message);
1551
+ return;
1552
+ }
1553
+ const output = renderStep(current, total, message, getColorCapability());
1554
+ process.stderr.write(output + "\n");
1555
+ },
1556
+ header(title, subtitle) {
1557
+ if (!_showPrimitives) return;
1558
+ if (!isRunningInTerminal()) {
1559
+ this.getServerFallback().header(title, subtitle);
1560
+ return;
1561
+ }
1562
+ const output = renderHeader(title, subtitle);
1563
+ process.stderr.write(output + "\n");
1564
+ },
1565
+ divider() {
1566
+ if (!_showPrimitives) return;
1567
+ if (!isRunningInTerminal()) {
1568
+ this.getServerFallback().divider();
1569
+ return;
1570
+ }
1571
+ const output = renderDivider();
1572
+ process.stderr.write(output + "\n");
1573
+ },
1574
+ blank() {
1575
+ if (!_showPrimitives) return;
1576
+ if (!isRunningInTerminal()) {
1577
+ this.getServerFallback().blank();
1578
+ return;
1579
+ }
1580
+ process.stderr.write("\n");
1581
+ },
1582
+ box(content, opts) {
1583
+ if (!_showPrimitives) return;
1584
+ if (!isRunningInTerminal()) {
1585
+ this.getServerFallback().box(content, opts);
1586
+ return;
1587
+ }
1588
+ const output = renderBox(content, opts, getColorCapability());
1589
+ process.stderr.write(output + "\n");
1590
+ },
1591
+ cliTable(rows, opts) {
1592
+ if (!_showPrimitives) return;
1593
+ if (!isRunningInTerminal()) {
1594
+ this.getServerFallback().cliTable(rows, opts);
1595
+ return;
1596
+ }
1597
+ const output = renderTable(rows, opts, getColorCapability());
1598
+ process.stderr.write(output + "\n");
1599
+ },
1600
+ spinner(message) {
1601
+ const logger = options.getLogger();
1602
+ if (!isRunningInTerminal() || options.config.outputMode === "silent") return new NoopSpinner(message, logger);
1603
+ return new SpinnerManager(message, options.config, logger);
1604
+ },
1605
+ getShowPrimitives() {
1606
+ return _showPrimitives;
1607
+ },
1608
+ setShowPrimitives(show) {
1609
+ _showPrimitives = show;
1610
+ },
1611
+ getServerFallback() {
1612
+ if (!_serverFallback) _serverFallback = new ServerFallback(options.getLogger());
1613
+ return _serverFallback;
1614
+ },
1615
+ isInTerminal() {
1616
+ return isRunningInTerminal();
1617
+ }
1618
+ };
1619
+ }
1620
+ //#endregion
1621
+ //#region src/Logger.ts
1622
+ THEME_PRESETS.default;
1623
+ /**
1624
+ * Clase principal Logger con capacidades avanzadas de logging
1625
+ *
1626
+ * @class Logger
1627
+ * @description Sistema completo de logging con temas, badges, contextos y exportación.
1628
+ * Detecta automáticamente el tema claro/oscuro del navegador.
1629
+ *
1630
+ * @example
1631
+ * // Uso básico sin configuración
1632
+ * import logger from '@mks2508/better-logger';
1633
+ * logger.info('Aplicación iniciada');
1634
+ * logger.success('Conexión establecida');
1635
+ *
1636
+ * @example
1637
+ * // Aplicar un preset temático
1638
+ * logger.preset('cyberpunk');
1639
+ * logger.warn('Advertencia con estilo neón');
1640
+ *
1641
+ * @example
1642
+ * // Logger con scope para componentes
1643
+ * const auth = logger.component('Autenticación');
1644
+ * auth.info('Usuario intentando login');
1645
+ * auth.success('Login exitoso');
1646
+ *
1647
+ */
1648
+ var Logger = class Logger {
1649
+ config;
1650
+ scopedPrefix;
1651
+ handlers = [];
1652
+ timers = /* @__PURE__ */ new Map();
1653
+ groupDepth = 0;
1654
+ cliProcessor;
1655
+ themeChangeListener;
1656
+ badgeList = [];
1657
+ displaySettings = {
1658
+ showTimestamp: true,
1659
+ showLocation: true,
1660
+ showBadges: true
1661
+ };
1662
+ serializerBridge;
1663
+ hookBridge;
1664
+ logContext;
1665
+ transportBridge;
1666
+ /** Fijado por `success()` para que `log()` salte su propio dispatch. */
1667
+ _successTagDispatched = false;
1668
+ styleManager;
1669
+ /** Controla si las CLI primitives (step, box, header, ...) deben renderizarse. */
1670
+ _showPrimitives = true;
1671
+ terminalBridge;
1672
+ /**
1673
+ * Referencia activa al smart-preset (fijada por `preset()`). Tipada como
1674
+ * `unknown` para mantener limpia la surface pública; la consume
1675
+ * `createStyledOutput`.
1676
+ */
1677
+ _activePreset;
1678
+ /**
1679
+ * Nombre del smart-preset activo. Se guarda aparte para que la detección
1680
+ * de cambio de tema pueda re-renderizar sin re-ejecutar el body del preset.
1681
+ */
1682
+ _activePresetName;
1683
+ /**
1684
+ * Overrides aplicados por el último `customize()`. Se conservan para que
1685
+ * `createStyledOutput` los lea después.
1686
+ */
1687
+ _customization;
1688
+ /**
1689
+ * Bindings propios de este logger (provenientes de llamadas a `child()`).
1690
+ * Source of truth única de la contribución de este logger a la cadena de contexto.
1691
+ * @private
1692
+ */
1693
+ _bindings = {};
1694
+ /**
1695
+ * Referencia al record de contexto mergueado del parent en el momento en
1696
+ * que se creó este logger. Junto con `_bindings`, forma la cadena de
1697
+ * contexto. `undefined` para el logger raíz.
1698
+ * @private
1699
+ */
1700
+ _parentContextRecord;
1701
+ /**
1702
+ * Crea una nueva instancia del Logger
1703
+ *
1704
+ * @param {Partial<LoggerConfig>} config - Configuración opcional del logger
1705
+ *
1706
+ * @example
1707
+ * // Logger con configuración personalizada
1708
+ * const logger = new Logger({
1709
+ * theme: 'neon',
1710
+ * globalPrefix: 'MiApp',
1711
+ * verbosity: 'debug',
1712
+ * bufferSize: 1000
1713
+ * });
1714
+ */
1715
+ constructor(config = {}) {
1716
+ this.config = {
1717
+ ...DEFAULT_CONFIG,
1718
+ ...config
1719
+ };
1720
+ this.serializerBridge = createSerializerBridge();
1721
+ this.hookBridge = createHookBridge();
1722
+ this.logContext = createLogContext({
1723
+ initialResource: this.config.resource,
1724
+ childLoggerFactory: (childConfig) => {
1725
+ return new Logger({
1726
+ ...this.config,
1727
+ ...childConfig
1728
+ });
1729
+ },
1730
+ getParentContextRecord: () => this._captureMergedContext()
1731
+ });
1732
+ this.transportBridge = createTransportBridge();
1733
+ this.styleManager = createStyleManager();
1734
+ this.terminalBridge = createTerminalBridge({
1735
+ config: this.config,
1736
+ getLogger: () => this
1737
+ });
1738
+ this.cliProcessor = createDefaultCLI();
1739
+ if (this.config.autoDetectTheme) this.setupAutoThemeDetection();
1740
+ }
1741
+ /**
1742
+ * Configura la detección automática de tema con listener de cambios
1743
+ * @private
1744
+ * @description Detecta automáticamente si el navegador está en modo claro u oscuro
1745
+ */
1746
+ setupAutoThemeDetection() {
1747
+ if (this.themeChangeListener) {
1748
+ this.themeChangeListener();
1749
+ this.themeChangeListener = null;
1750
+ }
1751
+ this.themeChangeListener = setupThemeChangeListener((theme) => {
1752
+ this.debug(`DevTools theme changed to: ${theme}`);
1753
+ });
1754
+ }
1755
+ /**
1756
+ * Obtiene la configuración actual del logger
1757
+ *
1758
+ * @returns {LoggerConfig} Configuración completa actual
1759
+ *
1760
+ * @example
1761
+ * const config = logger.getConfig();
1762
+ * console.log('Verbosidad actual:', config.verbosity);
1763
+ * console.log('Tema actual:', config.theme);
1764
+ *
1765
+ */
1766
+ getConfig() {
1767
+ return { ...this.config };
1768
+ }
1769
+ /**
1770
+ * Actualiza la configuración del logger
1771
+ *
1772
+ * @param {Partial<LoggerConfig>} updates - Propiedades a actualizar
1773
+ *
1774
+ * @example
1775
+ * logger.updateConfig({
1776
+ * verbosity: 'debug',
1777
+ * enableTimestamps: false,
1778
+ * theme: 'cyberpunk'
1779
+ * });
1780
+ *
1781
+ */
1782
+ updateConfig(updates) {
1783
+ const previousAutoDetect = this.config.autoDetectTheme;
1784
+ this.config = {
1785
+ ...this.config,
1786
+ ...updates
1787
+ };
1788
+ if (updates.autoDetectTheme !== void 0 && updates.autoDetectTheme !== previousAutoDetect) {
1789
+ if (updates.autoDetectTheme) this.setupAutoThemeDetection();
1790
+ else if (this.themeChangeListener) {
1791
+ this.themeChangeListener();
1792
+ this.themeChangeListener = null;
1793
+ }
1794
+ }
1795
+ }
1796
+ /**
1797
+ * Establece el prefijo global para todos los mensajes de log
1798
+ *
1799
+ * @param {string} prefix - Prefijo a usar
1800
+ *
1801
+ * @example
1802
+ * logger.setGlobalPrefix('MiApp');
1803
+ * logger.info('Iniciado'); // [MiApp] Iniciado
1804
+ *
1805
+ */
1806
+ setGlobalPrefix(prefix) {
1807
+ this.config.globalPrefix = prefix;
1808
+ }
1809
+ /**
1810
+ * Establece el nivel de verbosidad para filtrar la salida de logs
1811
+ *
1812
+ * @param {Verbosity} level - Nivel mínimo a mostrar ('debug' | 'info' | 'warn' | 'error' | 'critical' | 'silent')
1813
+ *
1814
+ * @example
1815
+ * logger.setVerbosity('warn'); // Solo muestra warn, error y critical
1816
+ * logger.setVerbosity('debug'); // Muestra todos los niveles
1817
+ * logger.setVerbosity('silent'); // No muestra nada
1818
+ *
1819
+ */
1820
+ setVerbosity(level) {
1821
+ this.config.verbosity = level;
1822
+ }
1823
+ /**
1824
+ * Establece el tema del logger
1825
+ *
1826
+ * @param {ThemeVariant} theme - Tema a aplicar ('default' | 'dark' | 'light' | 'neon' | 'minimal' | 'cyberpunk')
1827
+ *
1828
+ * @example
1829
+ * logger.setTheme('neon'); // Tema con colores neón
1830
+ * logger.setTheme('minimal'); // Tema minimalista
1831
+ * logger.setTheme('cyberpunk'); // Tema cyberpunk con efectos
1832
+ *
1833
+ */
1834
+ setTheme(theme) {
1835
+ if (hasPreset(theme)) {
1836
+ this.preset(theme);
1837
+ return;
1838
+ }
1839
+ if (this.styleManager.setTheme(theme)) {
1840
+ this.config.theme = theme;
1841
+ const bannersRecord = THEME_BANNERS;
1842
+ if (theme in bannersRecord) {
1843
+ const themeBanner = bannersRecord[theme];
1844
+ if (themeBanner) this.writeOutput(`%c${themeBanner.simple}`, "info", [themeBanner.style], []);
1845
+ }
1846
+ this.success(`Theme changed to: ${theme}`);
1847
+ } else this.error(`Invalid theme: ${theme}. Available:`, [...getAvailablePresets(), ...Object.keys(THEME_PRESETS)]);
1848
+ }
1849
+ /**
1850
+ * Establece el tipo de banner para mostrar en la inicialización
1851
+ *
1852
+ * @param {BannerType} bannerType - Tipo de banner ('simple' | 'ascii' | 'unicode' | 'svg' | 'animated')
1853
+ *
1854
+ * @example
1855
+ * logger.setBannerType('ascii'); // Banner con arte ASCII
1856
+ * logger.setBannerType('unicode'); // Banner con caracteres Unicode
1857
+ * logger.setBannerType('animated'); // Banner con animación
1858
+ *
1859
+ */
1860
+ setBannerType(bannerType) {
1861
+ this.config.bannerType = bannerType;
1862
+ this.success(`Banner type changed to: ${bannerType}`);
1863
+ }
1864
+ /**
1865
+ * Ejecuta `fn` dentro de un scope AsyncLocalStorage donde `bindings` se
1866
+ * merguean al contexto para todas las llamadas de log dentro de `fn`.
1867
+ *
1868
+ * Sin `fn` (el shape legacy de setter): no-op por backwards compatibility.
1869
+ * Preferir `child()` para bindings persistentes o `withContextAsync()`
1870
+ * para callbacks async.
1871
+ *
1872
+ * @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
1873
+ * @param fn - Función sincrónica opcional a ejecutar con los bindings en scope
1874
+ * @returns El valor de retorno de `fn`, o `undefined` si no se pasa `fn`
1875
+ *
1876
+ * @example
1877
+ * // Callback sincrónico scoped
1878
+ * logger.withContext({ requestId: 'r-42' }, () => {
1879
+ * doWork(); // los logs de aquí ven requestId en attributes
1880
+ * });
1881
+ *
1882
+ * @example
1883
+ * // Binding persistente: usar child()
1884
+ * const reqLog = logger.child({ requestId: 'r-42' });
1885
+ * reqLog.info('handling request'); // attributes incluye requestId
1886
+ *
1887
+ * @see {@link child} para una copia inmutable con el contexto mergueado
1888
+ * @see {@link withContextAsync} para la variante con callback async
1889
+ */
1890
+ withContext(bindings, fn) {
1891
+ return this.logContext.withContext(bindings, fn);
1892
+ }
1893
+ /**
1894
+ * Variante async de `withContext`. Ejecuta `fn` dentro de un scope
1895
+ * AsyncLocalStorage para que los bindings estén disponibles a todas las
1896
+ * llamadas de log async dentro de `fn`.
1897
+ *
1898
+ * @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
1899
+ * @param fn - Función async a ejecutar con los bindings en scope
1900
+ * @returns El valor de retorno de `fn`
1901
+ *
1902
+ * @example
1903
+ * await logger.withContextAsync({ requestId: 'r-42' }, async () => {
1904
+ * await fetchData(); // los logs de aquí ven requestId en attributes
1905
+ * });
1906
+ *
1907
+ * @see {@link child} para un child logger persistente
1908
+ * @see {@link withContext} para la variante con callback sincrónico
1909
+ */
1910
+ withContextAsync(bindings, fn) {
1911
+ return this.logContext.withContextAsync(bindings, fn);
1912
+ }
1913
+ /**
1914
+ * Devuelve una copia inmutable de este logger con el contexto extra bound.
1915
+ * Las llamadas futuras sobre el child emiten con el contexto mergueado,
1916
+ * sin mutar al parent — el patrón canónico de MDC.
1917
+ *
1918
+ * @param extra - Pares key-value a adjuntar (requestId, userId, ...)
1919
+ * @returns Un nuevo Logger con el contexto mergueado
1920
+ *
1921
+ * @example
1922
+ * const reqLog = logger.child({ requestId: req.id });
1923
+ * reqLog.info('start'); // emite attributes: { requestId }
1924
+ * logger.info('unrelated'); // NO afectado — el contexto del parent queda intacto
1925
+ *
1926
+ */
1927
+ child(extra) {
1928
+ const childLogger = this.logContext.child(extra);
1929
+ childLogger._parentContextRecord = childLogger["__parentSnapshot"] ?? {};
1930
+ childLogger._bindings = extra;
1931
+ return childLogger;
1932
+ }
1933
+ /**
1934
+ * Descarta todas las keys del contexto bound. Tras esta llamada, los
1935
+ * records emitidos dejan de llevar `attributes` hasta que
1936
+ * {@link withContext} o {@link child} restablezcan uno.
1937
+ *
1938
+ * @returns La misma instancia del logger, ahora sin contexto
1939
+ */
1940
+ clearContext() {
1941
+ this.logContext.clearContext();
1942
+ return this;
1943
+ }
1944
+ /**
1945
+ * Snapshot del contexto bound. El objeto devuelto es una shallow copy:
1946
+ * mutarlo NO afecta lo que emiten las llamadas de log posteriores.
1947
+ *
1948
+ * @returns Un snapshot read-only del contexto actual
1949
+ */
1950
+ getContext() {
1951
+ let merged = this._parentContextRecord ?? {};
1952
+ if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
1953
+ ...merged,
1954
+ ...this._bindings
1955
+ };
1956
+ return merged;
1957
+ }
1958
+ /**
1959
+ * Actualiza el resource OTel por defecto (service.name, version, env).
1960
+ * Se persiste en el campo `resource` de cada record emitido, salvo que
1961
+ * el propio record lo override.
1962
+ *
1963
+ * @param resource - Resource OTel parcial a merguear con el actual
1964
+ * @returns La misma instancia del logger, para chaining
1965
+ *
1966
+ * @example
1967
+ * logger.setResource({ 'service.name': 'api', 'service.version': '1.2.3' });
1968
+ *
1969
+ */
1970
+ setResource(resource) {
1971
+ this.logContext.setResource(resource);
1972
+ return this;
1973
+ }
1974
+ /**
1975
+ * Reinicia el logger a la configuración por defecto
1976
+ *
1977
+ * @example
1978
+ * logger.resetConfig();
1979
+ * // Todo vuelve a la configuración inicial
1980
+ *
1981
+ */
1982
+ resetConfig() {
1983
+ if (this.themeChangeListener) {
1984
+ this.themeChangeListener();
1985
+ this.themeChangeListener = null;
1986
+ }
1987
+ this.config = { ...DEFAULT_CONFIG };
1988
+ this.styleManager.resetStyles();
1989
+ if (this.config.autoDetectTheme) this.setupAutoThemeDetection();
1990
+ this.success("Logger configuration reset to defaults");
1991
+ }
1992
+ /**
1993
+ * Método de limpieza para eliminar listeners y liberar recursos.
1994
+ *
1995
+ * Vacía los transports (drain), limpia timers, suelta la lista de
1996
+ * handlers legacy, resetea el group depth y limpia el context.
1997
+ * Seguro de invocar múltiples veces.
1998
+ *
1999
+ * @example
2000
+ * // Antes de cerrar la aplicación
2001
+ * await logger.cleanup();
2002
+ *
2003
+ */
2004
+ async cleanup() {
2005
+ if (this.themeChangeListener) {
2006
+ try {
2007
+ this.themeChangeListener();
2008
+ } catch {}
2009
+ this.themeChangeListener = null;
2010
+ }
2011
+ await this.transportBridge.closeTransports();
2012
+ this.handlers.length = 0;
2013
+ this.timers.clear();
2014
+ this.badgeList = [];
2015
+ this.logContext.clearContext();
2016
+ this.groupDepth = 0;
2017
+ }
2018
+ /**
2019
+ * Aplica un preset inteligente - funciona perfectamente sin configuración
2020
+ *
2021
+ * @param {string} name - Nombre del preset a aplicar
2022
+ *
2023
+ * @example
2024
+ * // Presets disponibles
2025
+ * logger.preset('default'); // Limpio y adaptativo
2026
+ * logger.preset('cyberpunk'); // Colores neón, efectos brillantes
2027
+ * logger.preset('glassmorphism'); // Efectos de blur modernos
2028
+ * logger.preset('minimal'); // Minimalista y elegante
2029
+ * logger.preset('debug'); // Modo desarrollo detallado
2030
+ * logger.preset('production'); // Enfocado en producción
2031
+ *
2032
+ */
2033
+ preset(name) {
2034
+ if (!hasPreset(name)) {
2035
+ this.error(`Unknown preset: ${name}. Available presets:`, getAvailablePresets());
2036
+ return;
2037
+ }
2038
+ const presetConfig = getSmartPreset(name);
2039
+ if (presetConfig) {
2040
+ this.displaySettings.showTimestamp = presetConfig.timestamp?.show ?? true;
2041
+ this.displaySettings.showLocation = presetConfig.location?.show ?? true;
2042
+ this._activePreset = presetConfig;
2043
+ this._activePresetName = name;
2044
+ if (getEnvironment() === "browser") this.success(`Applied preset: ${name}`);
2045
+ }
2046
+ }
2047
+ /**
2048
+ * Lista todos los presets disponibles
2049
+ *
2050
+ * @returns {string[]} Array con nombres de presets disponibles
2051
+ *
2052
+ * @example
2053
+ * const disponibles = logger.presets();
2054
+ * console.log(disponibles); // ['default', 'cyberpunk', 'glassmorphism', ...]
2055
+ *
2056
+ */
2057
+ presets() {
2058
+ return getAvailablePresets();
2059
+ }
2060
+ /**
2061
+ * Oculta el timestamp en los logs
2062
+ *
2063
+ * @example
2064
+ * logger.hideTimestamp();
2065
+ * logger.info('Sin marca de tiempo'); // Sin timestamp visible
2066
+ *
2067
+ */
2068
+ hideTimestamp() {
2069
+ this.displaySettings.showTimestamp = false;
2070
+ return this;
2071
+ }
2072
+ /**
2073
+ * Muestra el timestamp en los logs
2074
+ *
2075
+ * @example
2076
+ * logger.showTimestamp();
2077
+ * logger.info('Con marca de tiempo'); // [2024-01-15 10:30:45] Con marca de tiempo
2078
+ *
2079
+ */
2080
+ showTimestamp() {
2081
+ this.displaySettings.showTimestamp = true;
2082
+ return this;
2083
+ }
2084
+ /**
2085
+ * Oculta la información de ubicación (archivo:línea) en los logs
2086
+ *
2087
+ * @example
2088
+ * logger.hideLocation();
2089
+ * logger.debug('Sin ubicación'); // Sin mostrar archivo:línea
2090
+ *
2091
+ */
2092
+ hideLocation() {
2093
+ this.displaySettings.showLocation = false;
2094
+ return this;
2095
+ }
2096
+ /**
2097
+ * Muestra la información de ubicación (archivo:línea) en los logs
2098
+ *
2099
+ * @example
2100
+ * logger.showLocation();
2101
+ * logger.debug('Con ubicación'); // app.js:42 Con ubicación
2102
+ *
2103
+ */
2104
+ showLocation() {
2105
+ this.displaySettings.showLocation = true;
2106
+ return this;
2107
+ }
2108
+ /**
2109
+ * Oculta los badges en los logs
2110
+ *
2111
+ * @example
2112
+ * logger.hideBadges();
2113
+ * const api = logger.api('REST');
2114
+ * api.info('Sin badges'); // Sin mostrar [API] [REST]
2115
+ *
2116
+ */
2117
+ hideBadges() {
2118
+ this.displaySettings.showBadges = false;
2119
+ return this;
2120
+ }
2121
+ /**
2122
+ * Muestra los badges en los logs
2123
+ *
2124
+ * @example
2125
+ * logger.showBadges();
2126
+ * const api = logger.api('GraphQL');
2127
+ * api.info('Con badges'); // [API] [GraphQL] Con badges
2128
+ *
2129
+ */
2130
+ showBadges() {
2131
+ this.displaySettings.showBadges = true;
2132
+ return this;
2133
+ }
2134
+ /**
2135
+ * Establece múltiples badges para los logs
2136
+ *
2137
+ * @param {string[]} badges - Array de badges a mostrar
2138
+ * @returns {this} Logger instance para encadenamiento
2139
+ *
2140
+ * @example
2141
+ * logger.badges(['v3', 'stable']).info('Release publicado');
2142
+ * logger.badges(['API', 'v2']).warn('Endpoint deprecado');
2143
+ *
2144
+ */
2145
+ badges(badges) {
2146
+ this.badgeList = [...badges];
2147
+ return this;
2148
+ }
2149
+ /**
2150
+ * Añade un badge individual a la lista
2151
+ *
2152
+ * @param {string} badge - Badge a añadir
2153
+ * @returns {this} Logger instance para encadenamiento
2154
+ *
2155
+ * @example
2156
+ * logger.badge('DEBUG').badge('AUTH').info('Token validado');
2157
+ *
2158
+ */
2159
+ badge(badge) {
2160
+ if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
2161
+ return this;
2162
+ }
2163
+ /**
2164
+ * Limpia todos los badges activos
2165
+ *
2166
+ * @returns {this} Logger instance para encadenamiento
2167
+ *
2168
+ * @example
2169
+ * logger.clearBadges().info('Sin badges');
2170
+ *
2171
+ */
2172
+ clearBadges() {
2173
+ this.badgeList = [];
2174
+ return this;
2175
+ }
2176
+ /**
2177
+ * Crea un logger scoped para un componente o módulo del dominio.
2178
+ *
2179
+ * El `ComponentLogger` resultante prepends un badge `[name]` a cada
2180
+ * mensaje y comparte configuración, transports y hooks con el logger
2181
+ * padre. Útil para trazar el origen de los logs en apps con muchos
2182
+ * módulos (Auth, DB, Cache, ...).
2183
+ *
2184
+ * @param {string} name - Nombre del componente que aparecerá como badge
2185
+ * @returns {ComponentLogger} Logger scoped para el componente
2186
+ *
2187
+ * @example
2188
+ * const auth = logger.component('Auth');
2189
+ * auth.info('Validando token'); // [Auth] Validando token
2190
+ * auth.success('Token válido');
2191
+ *
2192
+ * @see {@link api} para loggers de endpoints REST/GraphQL
2193
+ * @see {@link scope} para un scope genérico sin badge de componente
2194
+ */
2195
+ component(name) {
2196
+ return new ComponentLogger(this, name);
2197
+ }
2198
+ /**
2199
+ * Crea un logger scoped para un endpoint o surface de API.
2200
+ *
2201
+ * Como `component()` pero con styling orientado a APIs (badge `[API]`
2202
+ * por defecto más el nombre del sub-scope). Útil para distinguir
2203
+ * tráfico REST vs GraphQL vs WebSocket en los logs.
2204
+ *
2205
+ * @param {string} name - Nombre de la API o surface (p.ej. `'REST'`, `'GraphQL'`)
2206
+ * @returns {APILogger} Logger scoped para la API
2207
+ *
2208
+ * @example
2209
+ * const rest = logger.api('REST');
2210
+ * rest.info('GET /users/42'); // [API] [REST] GET /users/42
2211
+ *
2212
+ * @see {@link component} para loggers de componentes de dominio
2213
+ */
2214
+ api(name) {
2215
+ return new APILogger(this, name);
2216
+ }
2217
+ /**
2218
+ * Crea un logger scoped genérico con un prefijo.
2219
+ *
2220
+ * Variante minimal de `component()` / `api()`: solo aplica un prefijo
2221
+ * de scope sin badges ni styling especial. Útil para sub-módulos que
2222
+ * no encajan en las categorías de `component`/`api`.
2223
+ *
2224
+ * @param {string} name - Texto del prefijo de scope
2225
+ * @returns {ScopedLogger} Logger con el scope aplicado
2226
+ *
2227
+ * @example
2228
+ * const db = logger.scope('db');
2229
+ * db.info('Pool conectado'); // [db] Pool conectado
2230
+ *
2231
+ * @see {@link component} y {@link api} para variantes con badges
2232
+ */
2233
+ scope(name) {
2234
+ return new ScopedLogger(this, name);
2235
+ }
2236
+ /**
2237
+ * Personalización simple con configuración mínima
2238
+ *
2239
+ * @param {Object} overrides - Opciones de personalización
2240
+ * @param {Object} overrides.message - Configuración del mensaje
2241
+ * @param {Object} overrides.timestamp - Configuración del timestamp
2242
+ * @param {Object} overrides.location - Configuración de ubicación
2243
+ * @param {Object} overrides.level - Configuración del nivel
2244
+ * @param {Object} overrides.prefix - Configuración del prefijo
2245
+ * @param {string} overrides.spacing - Espaciado: 'compact' | 'normal' | 'spacious'
2246
+ *
2247
+ * @example
2248
+ * logger.customize({
2249
+ * message: { color: '#00ff00', size: '16px' },
2250
+ * timestamp: { show: false },
2251
+ * spacing: 'compact'
2252
+ * });
2253
+ *
2254
+ */
2255
+ customize(overrides) {
2256
+ if (overrides.timestamp?.show !== void 0) this.displaySettings.showTimestamp = overrides.timestamp.show;
2257
+ if (overrides.location?.show !== void 0) this.displaySettings.showLocation = overrides.location.show;
2258
+ if (overrides.prefix?.show !== void 0) {}
2259
+ this._customization = overrides;
2260
+ this.success("Customization applied");
2261
+ }
2262
+ /**
2263
+ * Añade un handler personalizado para extender funcionalidad
2264
+ *
2265
+ * @param {ILogHandler} handler - Handler que implementa ILogHandler
2266
+ *
2267
+ * @example
2268
+ * // Handler personalizado para enviar logs a servidor
2269
+ * logger.addHandler({
2270
+ * handle(level, message, args, metadata) {
2271
+ * fetch('/logs', { method: 'POST', body: JSON.stringify({ level, message }) });
2272
+ * }
2273
+ * });
2274
+ *
2275
+ * @example
2276
+ * // Para escribir a archivo, usa `addTransport` con un `FileTransport`
2277
+ * logger.addTransport({ target: new FileTransport({ destination: 'app.log' }) });
2278
+ *
2279
+ */
2280
+ addHandler(handler) {
2281
+ this.handlers.push(handler);
2282
+ }
2283
+ /**
2284
+ * Obtiene todos los handlers registrados
2285
+ *
2286
+ * @returns {ILogHandler[]} Array de handlers activos
2287
+ */
2288
+ getHandlers() {
2289
+ return [...this.handlers];
2290
+ }
2291
+ /**
2292
+ * Añade un serializador personalizado para un tipo específico
2293
+ *
2294
+ * @param type - Constructor del tipo a serializar
2295
+ * @param serializer - Función de serialización
2296
+ * @param priority - Prioridad (mayor = primero)
2297
+ *
2298
+ * @example
2299
+ * logger.addSerializer(Error, (err) => ({
2300
+ * name: err.name,
2301
+ * message: err.message,
2302
+ * stack: err.stack?.split('\n').slice(0, 5)
2303
+ * }));
2304
+ *
2305
+ */
2306
+ addSerializer(type, serializer, priority) {
2307
+ this.serializerBridge.addSerializer(type, serializer, priority);
2308
+ }
2309
+ /**
2310
+ * Elimina un serializador registrado
2311
+ *
2312
+ * @param type - Constructor del tipo a remover
2313
+ * @returns true si se eliminó
2314
+ *
2315
+ */
2316
+ removeSerializer(type) {
2317
+ return this.serializerBridge.removeSerializer(type);
2318
+ }
2319
+ /**
2320
+ * Obtiene el registry de serializadores
2321
+ *
2322
+ * @returns SerializerRegistry
2323
+ */
2324
+ getSerializerRegistry() {
2325
+ return this.serializerBridge.getSerializerRegistry();
2326
+ }
2327
+ /**
2328
+ * Registra un hook para un evento
2329
+ *
2330
+ * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
2331
+ * @param callback - Función a ejecutar
2332
+ * @param priority - Prioridad (mayor = primero)
2333
+ * @returns Función para desregistrar
2334
+ *
2335
+ * @example
2336
+ * const unsubscribe = logger.on('beforeLog', (entry) => {
2337
+ * entry.correlationId = getCorrelationId();
2338
+ * return entry;
2339
+ * });
2340
+ *
2341
+ */
2342
+ on(event, callback, priority) {
2343
+ return this.hookBridge.on(event, callback, priority);
2344
+ }
2345
+ /**
2346
+ * Registra un hook que se ejecuta solo una vez
2347
+ *
2348
+ * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
2349
+ * @param callback - Función a ejecutar
2350
+ * @param priority - Prioridad (mayor = primero)
2351
+ * @returns Función para desregistrar
2352
+ *
2353
+ */
2354
+ once(event, callback, priority) {
2355
+ return this.hookBridge.once(event, callback, priority);
2356
+ }
2357
+ /**
2358
+ * Elimina un hook registrado
2359
+ *
2360
+ * @param event - Evento del hook
2361
+ * @param callback - Callback a remover
2362
+ * @returns true si se eliminó
2363
+ *
2364
+ */
2365
+ off(event, callback) {
2366
+ return this.hookBridge.off(event, callback);
2367
+ }
2368
+ /**
2369
+ * Añade un middleware al pipeline
2370
+ *
2371
+ * @param middleware - Función middleware
2372
+ * @param priority - Prioridad (mayor = primero)
2373
+ * @returns Función para desregistrar
2374
+ *
2375
+ * @example
2376
+ * logger.use((entry, next) => {
2377
+ * entry.requestId = asyncLocalStorage.getStore()?.requestId;
2378
+ * next();
2379
+ * });
2380
+ *
2381
+ */
2382
+ use(middleware, priority) {
2383
+ return this.hookBridge.use(middleware, priority);
2384
+ }
2385
+ /**
2386
+ * Obtiene el HookManager
2387
+ *
2388
+ * @returns HookManager
2389
+ */
2390
+ getHookManager() {
2391
+ return this.hookBridge.getHookManager();
2392
+ }
2393
+ /**
2394
+ * Añade un transport para envío de logs
2395
+ *
2396
+ * @param target - Configuración del transport
2397
+ * @returns ID único del transport
2398
+ *
2399
+ * @example
2400
+ * // File transport
2401
+ * logger.addTransport({
2402
+ * target: 'file',
2403
+ * options: { destination: '/var/log/app.log' }
2404
+ * });
2405
+ *
2406
+ * @example
2407
+ * // HTTP transport con batching
2408
+ * logger.addTransport({
2409
+ * target: 'http',
2410
+ * options: {
2411
+ * url: 'https://logs.example.com',
2412
+ * batchSize: 100,
2413
+ * flushInterval: 5000
2414
+ * },
2415
+ * level: 'warn'
2416
+ * });
2417
+ *
2418
+ */
2419
+ addTransport(target) {
2420
+ return this.transportBridge.addTransport(target);
2421
+ }
2422
+ /**
2423
+ * Elimina un transport
2424
+ *
2425
+ * @param id - ID del transport a remover
2426
+ * @returns true si se eliminó
2427
+ *
2428
+ */
2429
+ removeTransport(id) {
2430
+ return this.transportBridge.removeTransport(id);
2431
+ }
2432
+ /**
2433
+ * Fuerza el flush de todos los transports
2434
+ *
2435
+ * @returns Promise que resuelve cuando todos los buffers están vaciados
2436
+ *
2437
+ */
2438
+ async flushTransports() {
2439
+ await this.transportBridge.flushTransports();
2440
+ }
2441
+ /**
2442
+ * Cierra todos los transports
2443
+ *
2444
+ * @returns Promise que resuelve cuando todos están cerrados
2445
+ *
2446
+ */
2447
+ async closeTransports() {
2448
+ await this.transportBridge.closeTransports();
2449
+ }
2450
+ /**
2451
+ * Obtiene el TransportManager
2452
+ *
2453
+ * @returns TransportManager o undefined si no hay transports
2454
+ */
2455
+ getTransportManager() {
2456
+ return this.transportBridge.getTransportManager();
2457
+ }
2458
+ /**
2459
+ * Verifica si un nivel de log debe mostrarse según la verbosidad actual.
2460
+ * @private
2461
+ * @param {LogLevel} level - Nivel de log a verificar
2462
+ * @returns {boolean} True si debe mostrarse, false si no
2463
+ */
2464
+ shouldLog(level) {
2465
+ if (this.config.verbosity === "silent") return false;
2466
+ return LOG_LEVELS[level] >= LOG_LEVELS[this.config.verbosity];
2467
+ }
2468
+ /**
2469
+ * Tag pendiente de inyectar en el siguiente `TransportRecord` emitido
2470
+ * por `log()`. Lo fijan `success()` y `logWithBindingsAndTag()` antes
2471
+ * de delegar; `log()` lo consume y lo resetea a `undefined`.
2472
+ *
2473
+ * @internal
2474
+ */
2475
+ _dispatchTag;
2476
+ /**
2477
+ * Computa el contexto completamente mergueado para este logger.
2478
+ *
2479
+ * La cadena de contexto se construye en el momento de crear el child:
2480
+ * cada child almacena el contexto fully-merged de su parent (en ese
2481
+ * instante) como `_parentContextRecord`. Esto implica que
2482
+ * `_parentContextRecord` ya contiene los bindings de todos los ancestros
2483
+ * en el orden de precedencia correcto (root primero, child más cercano al final).
2484
+ *
2485
+ * Orden de merge (gana el último):
2486
+ * 1. _parentContextRecord — snapshot del contexto mergueado del parent en la creación
2487
+ * 2. _bindings — bindings propios de este logger (llamadas a `child()`)
2488
+ * 3. ALS store — scope de `withContext`/`withContextAsync` (prioridad máxima)
2489
+ *
2490
+ * @internal
2491
+ * @returns El record de contexto mergueado
2492
+ */
2493
+ _getMergedContext() {
2494
+ let merged = this._parentContextRecord ?? {};
2495
+ if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
2496
+ ...merged,
2497
+ ...this._bindings
2498
+ };
2499
+ const alsContext = this.logContext._getAlsStore?.() ?? {};
2500
+ if (alsContext && Object.keys(alsContext).length > 0) merged = {
2501
+ ...merged,
2502
+ ...alsContext
2503
+ };
2504
+ return merged;
2505
+ }
2506
+ /** @internal Expone el contexto base mergueado (sin ALS) a la closure de la child factory de LogContext. */
2507
+ _captureMergedContext() {
2508
+ let merged = this._parentContextRecord ?? {};
2509
+ if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
2510
+ ...merged,
2511
+ ...this._bindings
2512
+ };
2513
+ return merged;
2514
+ }
2515
+ /**
2516
+ * Construye y despacha un `TransportRecord` al {@link TransportManager}
2517
+ * (no-op si no hay transports registrados). Lo comparten todos los
2518
+ * caminos de log — `log()`, `success()` y los métodos visuales como
2519
+ * `table()` / `group()` / `time()` — para que toda emisión atraviese
2520
+ * el mismo pipeline de transports.
2521
+ *
2522
+ * @protected
2523
+ * @param {LogLevel} level - Nivel canónico (trace/debug/info/warn/error/critical)
2524
+ * @param {string} message - Mensaje final, post-hook
2525
+ * @param {string | undefined} prefix - Prefijo efectivo (global + scope)
2526
+ * @param {StackInfo | null} stackInfo - Ubicación del caller, opcional
2527
+ * @param {Partial<TransportRecord>} [extra] - Campos extra a mergear en el record
2528
+ * (p.ej. `{ tag: 'success' }` o `attributes` adicionales)
2529
+ */
2530
+ dispatchToTransports(level, message, prefix, stackInfo, extra) {
2531
+ const record = {
2532
+ level,
2533
+ levelValue: LOG_LEVELS[level],
2534
+ severityNumber: LOG_LEVEL_TO_SEVERITY_NUMBER[level],
2535
+ severityText: LOG_LEVEL_TO_SEVERITY_TEXT[level],
2536
+ time: Date.now(),
2537
+ msg: message,
2538
+ prefix,
2539
+ location: stackInfo ? {
2540
+ file: stackInfo.file,
2541
+ line: stackInfo.line,
2542
+ column: stackInfo.column,
2543
+ function: stackInfo.function
2544
+ } : void 0,
2545
+ attributes: Object.keys(this.logContext._getContextRecord()).length > 0 ? toLogAttributes(this.logContext._getContextRecord()) : void 0,
2546
+ resource: this.logContext._getResource() ? { ...this.logContext._getResource() } : void 0,
2547
+ ...extra
2548
+ };
2549
+ this.transportBridge.writeRecord(record);
2550
+ }
2551
+ /**
2552
+ * Obtiene el prefijo efectivo (global + scope)
2553
+ * @private
2554
+ * @returns {string | undefined} Prefijo combinado o undefined
2555
+ */
2556
+ getEffectivePrefix() {
2557
+ const parts = [this.config.globalPrefix, this.scopedPrefix].filter(Boolean);
2558
+ return parts.length > 0 ? parts.join(":") : void 0;
2559
+ }
2560
+ /**
2561
+ * Método central de logging. Espera el hook pipeline `beforeLog`
2562
+ * antes de despachar a consola y transports, para que redacciones
2563
+ * o enriquecimientos (PII, correlation IDs) se reflejen en el
2564
+ * mensaje emitido.
2565
+ *
2566
+ * Los callers fire-and-forget (p.ej. `logger.info(...)` sin `await`)
2567
+ * siguen funcionando: el `Promise<void>` resultante se descarta.
2568
+ * Se recomienda `await` cuando los hooks `beforeLog` mutan `message`.
2569
+ *
2570
+ * El tag opcional (`TransportRecord.tag`) NO se pasa como argumento:
2571
+ * se establece vía `_dispatchTag` (ver `success()` y
2572
+ * {@link logWithBindingsAndTag}) antes de invocar este método.
2573
+ *
2574
+ * @protected
2575
+ * @param {LogLevel} level - Nivel del log
2576
+ * @param {unknown[]} args - Argumentos a loggear (mensaje + datos)
2577
+ * @returns {Promise<void>} Promesa que resuelve al completar el dispatch
2578
+ *
2579
+ */
2580
+ async log(level, ...args) {
2581
+ if (!this.shouldLog(level)) return;
2582
+ const dispatchTag = this._dispatchTag;
2583
+ this._dispatchTag = void 0;
2584
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2585
+ const prefix = this.getEffectivePrefix();
2586
+ const timestamp = formatTimestamp();
2587
+ const serializedArgs = args.map((arg) => this.serializerBridge.getSerializerRegistry().serialize(arg));
2588
+ let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : "";
2589
+ if (this.badgeList.length > 0 && this.displaySettings.showBadges) message = this.badgeList.map((b) => `[${b}]`).join("") + " " + message;
2590
+ const additionalArgs = serializedArgs.slice(1);
2591
+ const hookEntry = {
2592
+ level,
2593
+ message,
2594
+ args: serializedArgs,
2595
+ timestamp,
2596
+ prefix,
2597
+ stackInfo: stackInfo ?? void 0
2598
+ };
2599
+ let processed;
2600
+ try {
2601
+ processed = await this.hookBridge.getHookManager().emit("beforeLog", hookEntry);
2602
+ } catch (error) {
2603
+ console.error("HookManager beforeLog failed:", error);
2604
+ processed = hookEntry;
2605
+ }
2606
+ message = processed.message;
2607
+ const [format, ...styles] = createStyledOutput(level, this.styleManager.getStyles(), prefix, message, this.displaySettings.showLocation ? stackInfo : null, this.config.autoDetectTheme, this._activePreset, this._activePresetName);
2608
+ const finalFormat = " ".repeat(this.groupDepth) + format;
2609
+ this.writeOutput(finalFormat, level, styles, additionalArgs);
2610
+ const metadata = {
2611
+ timestamp,
2612
+ level,
2613
+ prefix,
2614
+ stackInfo: stackInfo ?? void 0
2615
+ };
2616
+ this.handlers.forEach((handler) => {
2617
+ try {
2618
+ handler.handle(level, message, serializedArgs, metadata);
2619
+ } catch (error) {
2620
+ console.error("Log handler failed:", error);
2621
+ }
2622
+ });
2623
+ if (dispatchTag !== void 0) this.dispatchToTransports(level, message, prefix, stackInfo, { tag: dispatchTag });
2624
+ else this.dispatchToTransports(level, message, prefix, stackInfo);
2625
+ this.hookBridge.getHookManager().emit("afterLog", processed).catch(() => {});
2626
+ }
2627
+ /**
2628
+ * Emite un log aplicando bindings (badges, scope) al prefijo del
2629
+ * mensaje antes de delegar en {@link Logger.log}.
2630
+ *
2631
+ * No es API pública de consumo: existe para que `ScopedLogger`
2632
+ * (`component()` / `api()` / `scope()`) pueda reutilizar el pipeline
2633
+ * central de `log()` sin duplicar la lógica de styling/badges.
2634
+ *
2635
+ * @internal
2636
+ * @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
2637
+ * @param {LogLevel} level - Nivel de log
2638
+ * @param {unknown[]} args - Argumentos a loggear
2639
+ * @returns {Promise<void>} Promesa del dispatch
2640
+ *
2641
+ * @see {@link logWithBindingsAndTag} para la variante con `tag`
2642
+ */
2643
+ logWithBindings(bindings, level, ...args) {
2644
+ if (!this.shouldLog(level)) return Promise.resolve();
2645
+ let prefix = "";
2646
+ const colorCapability = getColorCapability();
2647
+ if (bindings.badges?.length) prefix += bindings.badges.map((b) => formatBadge(b, "pill", colorCapability, "#00ff88")).join(" ") + " ";
2648
+ if (bindings.scope) prefix += formatBadge(bindings.scope, "pill", colorCapability, "#00ffff") + " ";
2649
+ if (prefix && args.length > 0) args[0] = prefix + String(args[0]);
2650
+ return this.log(level, ...args);
2651
+ }
2652
+ /**
2653
+ * Como {@link logWithBindings} pero fija `_dispatchTag` antes de
2654
+ * delegar, para que `log()` despache el `TransportRecord` con el
2655
+ * tag indicado. Lo usa `ScopedLogger.success()` para propagar
2656
+ * `tag: 'success'` a través del pipeline normal de `log()`.
2657
+ *
2658
+ * @internal
2659
+ * @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
2660
+ * @param {LogLevel} level - Nivel de log
2661
+ * @param {LogTag} tag - Tag a inyectar en el `TransportRecord`
2662
+ * @param {unknown[]} args - Argumentos a loggear
2663
+ * @returns {Promise<void>} Promesa del dispatch
2664
+ */
2665
+ logWithBindingsAndTag(bindings, level, tag, ...args) {
2666
+ this._dispatchTag = tag;
2667
+ return this.logWithBindings(bindings, level, ...args);
2668
+ }
2669
+ /**
2670
+ * Registra mensajes de debug (nivel más verboso junto a `trace`).
2671
+ * Pensado para diagnóstico de desarrollo: valores intermedios, flags
2672
+ * de control flow, estado interno. Devuelve `Promise<void>`.
2673
+ *
2674
+ * Filtrado por defecto cuando `verbosity > 'debug'` (ver `setVerbosity`).
2675
+ *
2676
+ * @param {unknown[]} args - Mensaje + datos a inspeccionar
2677
+ * @returns {Promise<void>} Promesa del dispatch
2678
+ *
2679
+ * @example
2680
+ * logger.debug('Estado interno:', { conn, queueSize });
2681
+ * logger.debug('Entrando en branch X');
2682
+ *
2683
+ * @see {@link trace} para diagnósticos aún más granulares
2684
+ * @see {@link setVerbosity} para controlar el nivel mínimo visible
2685
+ */
2686
+ debug(...args) {
2687
+ return this.log("debug", ...args);
2688
+ }
2689
+ /**
2690
+ * Registra mensajes informativos. El `await` retorna cuando el hook
2691
+ * `beforeLog` y el dispatch a transports han terminado.
2692
+ *
2693
+ * @param args - Mensajes y datos informativos
2694
+ *
2695
+ * @example
2696
+ * logger.info('Servidor iniciado en puerto 3000');
2697
+ * await logger.info('Procesando', totalItems, 'elementos'); // espera hooks
2698
+ *
2699
+ */
2700
+ info(...args) {
2701
+ return this.log("info", ...args);
2702
+ }
2703
+ /**
2704
+ * Registra mensajes de advertencia.
2705
+ *
2706
+ * @param args - Mensajes de advertencia
2707
+ *
2708
+ */
2709
+ warn(...args) {
2710
+ return this.log("warn", ...args);
2711
+ }
2712
+ /**
2713
+ * Registra mensajes de error.
2714
+ *
2715
+ * @param args - Mensaje de error y stack traces
2716
+ *
2717
+ */
2718
+ error(...args) {
2719
+ return this.log("error", ...args);
2720
+ }
2721
+ /**
2722
+ * Registra mensajes de éxito. Mapeado internamente a nivel `info` con
2723
+ * styling de success y `record.tag = 'success'` para que los transports
2724
+ * puedan distinguirlo (sin perder info semantics para filtering).
2725
+ *
2726
+ * @param args - Mensaje + datos adicionales
2727
+ *
2728
+ * @example
2729
+ * logger.success('Base de datos conectada');
2730
+ * logger.success('Usuario creado con ID:', userId);
2731
+ * logger.success('✓ Tests pasados: 42/42');
2732
+ *
2733
+ */
2734
+ async success(...args) {
2735
+ if (!this.shouldLog("info")) return;
2736
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2737
+ const prefix = this.getEffectivePrefix();
2738
+ const timestamp = formatTimestamp();
2739
+ const serializedArgs = args.map((arg) => this.serializerBridge.getSerializerRegistry().serialize(arg));
2740
+ let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : "";
2741
+ if (this.badgeList.length > 0 && this.displaySettings.showBadges) message = this.badgeList.map((b) => `[${b}]`).join("") + " " + message;
2742
+ const additionalArgs = serializedArgs.slice(1);
2743
+ const hookEntry = {
2744
+ level: "info",
2745
+ message,
2746
+ args: serializedArgs,
2747
+ timestamp,
2748
+ prefix,
2749
+ stackInfo: stackInfo ?? void 0
2750
+ };
2751
+ try {
2752
+ message = (await this.hookBridge.getHookManager().emit("beforeLog", hookEntry)).message;
2753
+ } catch {}
2754
+ const [format, ...styles] = createStyledOutput("info", this.styleManager.getStyles(), prefix, message, this.displaySettings.showLocation ? stackInfo : null, this.config.autoDetectTheme, this._activePreset, this._activePresetName);
2755
+ const successStyle = this.styleManager.getStyles().success;
2756
+ const emoji = successStyle?.emoji ?? "✅";
2757
+ const label = successStyle?.label ?? "SUCCESS";
2758
+ const successFormat = format.replace(/ℹ️ INFO/, `${emoji} ${label}`);
2759
+ const finalFormat = " ".repeat(this.groupDepth) + successFormat;
2760
+ this.writeOutput(finalFormat, "info", styles, additionalArgs);
2761
+ const metadata = {
2762
+ timestamp,
2763
+ level: "info",
2764
+ prefix,
2765
+ stackInfo: stackInfo ?? void 0
2766
+ };
2767
+ this.handlers.forEach((handler) => {
2768
+ try {
2769
+ handler.handle("info", message, args, metadata);
2770
+ } catch (error) {
2771
+ console.error("Log handler failed:", error);
2772
+ }
2773
+ });
2774
+ this._dispatchTag = "success";
2775
+ await this.log("info", ...args);
2776
+ this.hookBridge.getHookManager().emit("afterLog", hookEntry).catch(() => {});
2777
+ }
2778
+ /**
2779
+ * Registra información de trace (nivel más bajo, debajo de debug).
2780
+ * Alineado con OpenTelemetry `TRACE` severity (1-4).
2781
+ *
2782
+ * @param args - Datos muy verbosos (entrada/salida de funciones, valores intermedios)
2783
+ *
2784
+ * @example
2785
+ * logger.trace('Entrando en función processData');
2786
+ * logger.trace('Variables intermedias:', { a, b, c });
2787
+ *
2788
+ */
2789
+ trace(...args) {
2790
+ this.log("trace", ...args);
2791
+ }
2792
+ /**
2793
+ * Registra errores críticos (prioridad más alta).
2794
+ *
2795
+ * @param args - Errores críticos del sistema
2796
+ *
2797
+ * @example
2798
+ * await logger.critical('Sistema caído - reinicio inmediato requerido');
2799
+ *
2800
+ */
2801
+ critical(...args) {
2802
+ return this.log("critical", ...args);
2803
+ }
2804
+ /**
2805
+ * Muestra datos en formato de tabla. Pasa por la pipeline completa
2806
+ * (outputMode-respecting writeOutput + transports + hooks).
2807
+ *
2808
+ * @param data - Array de objetos o matriz
2809
+ * @param columns - Columnas específicas a mostrar (opcional)
2810
+ *
2811
+ * @example
2812
+ * logger.table([{ id: 1, nombre: 'Juan' }, { id: 2, nombre: 'María' }]);
2813
+ *
2814
+ */
2815
+ table(data, columns) {
2816
+ if (!this.shouldLog("info")) return;
2817
+ const prefix = this.getEffectivePrefix();
2818
+ const tableStyle = StylePresets.accent().build();
2819
+ const format = `%c${`📊 TABLE${prefix ? ` [${prefix}]` : ""}`}`;
2820
+ const styles = [tableStyle];
2821
+ this.writeOutput(format, "info", styles, []);
2822
+ [...columns ? [columns] : []];
2823
+ if (this.config.outputMode !== "silent") if (columns) console.table(data, columns);
2824
+ else console.table(data);
2825
+ const message = `table:${Array.isArray(data) ? `${data.length} rows` : "data"}`;
2826
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2827
+ this.dispatchToTransports("info", message, prefix, stackInfo, { attributes: {
2828
+ ...this.logContext._getContextRecord(),
2829
+ "logger.visual": "table",
2830
+ "logger.data": JSON.stringify(data).slice(0, 4096),
2831
+ ...columns ? { "logger.columns": columns.join(",") } : {}
2832
+ } });
2833
+ }
2834
+ /**
2835
+ * Inicia un grupo colapsable en la consola. Emite un marker a
2836
+ * transports con `attributes.logger.visual = 'groupStart'` para que
2837
+ * backends puedan reconstruir la jerarquía.
2838
+ *
2839
+ * @param label - Etiqueta del grupo
2840
+ * @param collapsed - Si el grupo inicia colapsado (default: false)
2841
+ *
2842
+ * @example
2843
+ * logger.group('Procesando usuarios');
2844
+ * logger.info('Usuario 1 procesado');
2845
+ * logger.groupEnd();
2846
+ *
2847
+ */
2848
+ group(label, collapsed = false) {
2849
+ 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();
2850
+ const format = `%c📁 ${label}`;
2851
+ if (this.config.outputMode !== "silent") if (collapsed) console.groupCollapsed(format, groupStyle);
2852
+ else console.group(format, groupStyle);
2853
+ this.groupDepth++;
2854
+ const prefix = this.getEffectivePrefix();
2855
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2856
+ this.dispatchToTransports("info", `group:start:${label}`, prefix, stackInfo, { attributes: {
2857
+ ...this.logContext._getContextRecord(),
2858
+ "logger.visual": "groupStart",
2859
+ "logger.group.label": label,
2860
+ "logger.group.collapsed": collapsed,
2861
+ "logger.group.depth": this.groupDepth
2862
+ } });
2863
+ }
2864
+ /**
2865
+ * Finaliza el grupo actual de la consola. Emite un marker a transports
2866
+ * simétrico al `group()` start, para que backends puedan cerrar la
2867
+ * jerarquía correctamente.
2868
+ *
2869
+ * @example
2870
+ * logger.group('Operaciones');
2871
+ * logger.info('Operación 1');
2872
+ * logger.groupEnd();
2873
+ *
2874
+ */
2875
+ groupEnd() {
2876
+ if (this.groupDepth > 0) {
2877
+ this.groupDepth--;
2878
+ if (this.config.outputMode !== "silent") console.groupEnd();
2879
+ const prefix = this.getEffectivePrefix();
2880
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2881
+ this.dispatchToTransports("info", "group:end", prefix, stackInfo, { attributes: {
2882
+ ...this.logContext._getContextRecord(),
2883
+ "logger.visual": "groupEnd",
2884
+ "logger.group.depth": this.groupDepth
2885
+ } });
2886
+ }
2887
+ }
2888
+ /**
2889
+ * Inicia un temporizador con la etiqueta dada
2890
+ *
2891
+ * @param {string} label - Etiqueta identificadora del temporizador
2892
+ *
2893
+ * @example
2894
+ * logger.time('proceso-datos');
2895
+ * // ... operación costosa ...
2896
+ * logger.timeEnd('proceso-datos'); // ⏱️ Timer ended: proceso-datos - 1523.45ms
2897
+ *
2898
+ */
2899
+ time(label) {
2900
+ const timer = {
2901
+ label,
2902
+ startTime: (typeof performance !== "undefined" ? performance : Date).now()
2903
+ };
2904
+ this.timers.set(label, timer);
2905
+ const timerStyle = StylePresets.warning().build();
2906
+ const format = `%c⏱️ Timer started: ${label}`;
2907
+ this.writeOutput(format, "debug", [timerStyle], []);
2908
+ }
2909
+ /**
2910
+ * Finaliza un temporizador y muestra el tiempo transcurrido
2911
+ *
2912
+ * @param {string} label - Etiqueta del temporizador a finalizar
2913
+ * @returns {number} Milisegundos transcurridos, o `-1` si no se encuentra el timer
2914
+ *
2915
+ * @example
2916
+ * logger.time('consulta-db');
2917
+ * await consultarBaseDatos();
2918
+ * const elapsed = logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
2919
+ *
2920
+ */
2921
+ timeEnd(label) {
2922
+ const timer = this.timers.get(label);
2923
+ if (!timer) {
2924
+ this.warn(`Timer '${label}' does not exist`);
2925
+ return -1;
2926
+ }
2927
+ const elapsed = (typeof performance !== "undefined" ? performance : Date).now() - timer.startTime;
2928
+ this.timers.delete(label);
2929
+ const timerStyle = StylePresets.success().build();
2930
+ const format = `%c⏱️ Timer ended: ${label} - ${elapsed.toFixed(2)}ms`;
2931
+ this.writeOutput(format, "info", [timerStyle], []);
2932
+ const prefix = this.getEffectivePrefix();
2933
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2934
+ this.dispatchToTransports("info", `timer:${label}`, prefix, stackInfo, {
2935
+ tag: "success",
2936
+ attributes: {
2937
+ ...this.logContext._getContextRecord(),
2938
+ "logger.visual": "timer",
2939
+ "logger.timer.label": label,
2940
+ "logger.timer.elapsedMs": elapsed
2941
+ }
2942
+ });
2943
+ return elapsed;
2944
+ }
2945
+ /**
2946
+ * Muestra un banner con el tipo especificado o configurado
2947
+ *
2948
+ * @param {BannerType} bannerType - Tipo de banner (opcional)
2949
+ *
2950
+ * @example
2951
+ * logger.showBanner('ascii'); // Banner ASCII art
2952
+ * logger.showBanner('unicode'); // Banner con caracteres Unicode
2953
+ * logger.showBanner('svg'); // Banner con gráfico SVG
2954
+ * logger.showBanner(); // Usa el tipo configurado
2955
+ *
2956
+ */
2957
+ showBanner(bannerType) {
2958
+ displayInitBanner(bannerType ? bannerType : this.config.bannerType);
2959
+ }
2960
+ /**
2961
+ * Registra mensaje con imagen SVG de fondo
2962
+ *
2963
+ * @param {string} message - Mensaje a mostrar
2964
+ * @param {string} svgContent - Contenido SVG personalizado (opcional)
2965
+ * @param {StyleOptions} options - Opciones de estilo (ancho, alto, padding)
2966
+ *
2967
+ * @example
2968
+ * // SVG automático con gradiente
2969
+ * logger.logWithSVG('🎆 Bienvenido a Better Logger');
2970
+ *
2971
+ * @example
2972
+ * // SVG personalizado
2973
+ * const customSVG = '<svg>...</svg>';
2974
+ * logger.logWithSVG('Logo', customSVG, { width: 400, height: 100 });
2975
+ *
2976
+ */
2977
+ logWithSVG(message, svgContent, options = {}) {
2978
+ if (!this.shouldLog("info")) return;
2979
+ const { width = 300, height = 60, padding = "30px 150px" } = options;
2980
+ let svgDataUri = "";
2981
+ if (svgContent) svgDataUri = `data:image/svg+xml,${encodeURIComponent(svgContent)}`;
2982
+ else {
2983
+ 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>`;
2984
+ svgDataUri = `data:image/svg+xml,${encodeURIComponent(defaultSVG)}`;
2985
+ }
2986
+ const svgStyle = new StyleBuilder().bg(`url("${svgDataUri}") no-repeat center center`).padding(padding).color("transparent").rounded("4px").build();
2987
+ this.writeOutput(`%c${message}`, "info", [svgStyle], []);
2988
+ const prefix = this.getEffectivePrefix();
2989
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
2990
+ this.dispatchToTransports("info", `svg:${message}`, prefix, stackInfo, { attributes: {
2991
+ ...this.logContext._getContextRecord(),
2992
+ "logger.visual": "svg",
2993
+ "logger.svg.width": width,
2994
+ "logger.svg.height": height
2995
+ } });
2996
+ }
2997
+ /**
2998
+ * Registra mensaje con gradiente animado de fondo
2999
+ *
3000
+ * @param {string} message - Mensaje a animar
3001
+ * @param {number} duration - Duración de la animación en segundos (default: 3)
3002
+ *
3003
+ * @example
3004
+ * logger.logAnimated('🌈 Animación en progreso');
3005
+ * logger.logAnimated('Cargando...', 5); // Animación de 5 segundos
3006
+ *
3007
+ */
3008
+ logAnimated(message, duration = 3) {
3009
+ if (!this.shouldLog("info")) return;
3010
+ if (typeof document !== "undefined") {
3011
+ if (!document.getElementById("logger-animations")) {
3012
+ const style = document.createElement("style");
3013
+ style.id = "logger-animations";
3014
+ style.textContent = `
3015
+ @keyframes loggerGradient {
3016
+ 0% { background-position: 0% 50%; }
3017
+ 50% { background-position: 100% 50%; }
3018
+ 100% { background-position: 0% 50%; }
3019
+ }
3020
+ `;
3021
+ document.head.appendChild(style);
3022
+ }
3023
+ }
3024
+ 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();
3025
+ this.writeOutput(`%c${message}`, "info", [animatedStyle], []);
3026
+ const prefix = this.getEffectivePrefix();
3027
+ const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
3028
+ this.dispatchToTransports("info", `animated:${message}`, prefix, stackInfo, { attributes: {
3029
+ ...this.logContext._getContextRecord(),
3030
+ "logger.visual": "animated",
3031
+ "logger.animation.durationSec": duration
3032
+ } });
3033
+ }
3034
+ /**
3035
+ * Muestra un indicador de progreso de pasos en la terminal
3036
+ *
3037
+ * @param {number} current - Número de paso actual
3038
+ * @param {number} total - Número total de pasos
3039
+ * @param {string} message - Descripción del paso
3040
+ *
3041
+ * @example
3042
+ * logger.step(1, 5, 'Analyzing repository...');
3043
+ * logger.step(2, 5, 'Generating commit message...');
3044
+ *
3045
+ */
3046
+ step(current, total, message) {
3047
+ this.terminalBridge.step(current, total, message);
3048
+ }
3049
+ /**
3050
+ * Muestra un header con estilo y subtítulo opcional
3051
+ *
3052
+ * @param {string} title - Texto del título principal
3053
+ * @param {string} subtitle - Subtítulo opcional (se renderiza atenuado)
3054
+ *
3055
+ * @example
3056
+ * logger.header('Commit Wizard', 'v2.0.0');
3057
+ *
3058
+ */
3059
+ header(title, subtitle) {
3060
+ this.terminalBridge.header(title, subtitle);
3061
+ }
3062
+ /**
3063
+ * Muestra una línea divisoria horizontal
3064
+ *
3065
+ * @example
3066
+ * logger.divider();
3067
+ *
3068
+ */
3069
+ divider() {
3070
+ this.terminalBridge.divider();
3071
+ }
3072
+ /**
3073
+ * Emite una línea en blanco
3074
+ *
3075
+ * @example
3076
+ * logger.blank();
3077
+ *
3078
+ */
3079
+ blank() {
3080
+ this.terminalBridge.blank();
3081
+ }
3082
+ /**
3083
+ * Renderiza contenido dentro de un box con borde
3084
+ *
3085
+ * @param {string} content - String de contenido (puede contener newlines)
3086
+ * @param {IBoxOptions} options - Opciones de renderizado del box
3087
+ *
3088
+ * @example
3089
+ * logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
3090
+ *
3091
+ */
3092
+ box(content, options) {
3093
+ this.terminalBridge.box(content, options);
3094
+ }
3095
+ /**
3096
+ * Renderiza un array de objetos como una tabla ASCII formateada.
3097
+ * Distinto del método `table()` existente, que usa `console.table`.
3098
+ *
3099
+ * @param {Record<string, unknown>[]} rows - Array de objetos fila
3100
+ * @param {ITableOptions} options - Opciones de renderizado de la tabla
3101
+ *
3102
+ * @example
3103
+ * logger.cliTable([
3104
+ * { provider: 'Groq', status: 'Available', model: 'llama-3.3-70b' },
3105
+ * { provider: 'Gemini', status: 'Configured', model: 'gemini-2.5-flash' },
3106
+ * ]);
3107
+ *
3108
+ */
3109
+ cliTable(rows, options) {
3110
+ this.terminalBridge.cliTable(rows, options);
3111
+ }
3112
+ /**
3113
+ * Crea un handle de spinner para mostrar progreso durante operaciones async.
3114
+ * Devuelve un `NoopSpinner` en entornos non-TTY.
3115
+ *
3116
+ * @param {string} message - Texto inicial del spinner
3117
+ * @returns {ISpinnerHandle} Controller del spinner
3118
+ *
3119
+ * @example
3120
+ * const s = logger.spinner('Analyzing repository...');
3121
+ * s.start();
3122
+ * await analyzeRepo();
3123
+ * s.succeed('Analysis complete (1.2s)');
3124
+ *
3125
+ */
3126
+ spinner(message) {
3127
+ return this.terminalBridge.spinner(message);
3128
+ }
3129
+ /**
3130
+ * Fija el nivel de verbosidad del CLI, controlando a la vez la verbosidad
3131
+ * de logs y la visibilidad de las primitives
3132
+ *
3133
+ * @param {CLILogLevel} level - Nivel de log del CLI
3134
+ *
3135
+ * @example
3136
+ * logger.setCLILevel('quiet'); // Solo errors, sin CLI primitives
3137
+ * logger.setCLILevel('verbose'); // Debug logs + todas las CLI primitives
3138
+ *
3139
+ */
3140
+ setCLILevel(level) {
3141
+ const mapping = CLI_LEVEL_MAP[level];
3142
+ this.setVerbosity(mapping.verbosity);
3143
+ this.terminalBridge.setShowPrimitives(mapping.showPrimitives);
3144
+ this.config.cliLevel = level;
3145
+ }
3146
+ /**
3147
+ * Devuelve el nivel de log del CLI actual
3148
+ * @returns {CLILogLevel} Nivel de log del CLI actual
3149
+ */
3150
+ get cliLevel() {
3151
+ return this.config.cliLevel ?? "normal";
3152
+ }
3153
+ /**
3154
+ * Escribe output formateado al destino configurado.
3155
+ * Respeta la configuración `outputMode` para output a consola, silencioso o custom.
3156
+ *
3157
+ * @private
3158
+ * @param {string} message - Mensaje de log formateado
3159
+ * @param {LogLevel} level - Nivel de log
3160
+ * @param {string[]} styles - Estilos CSS para la consola del navegador
3161
+ * @param {unknown[]} additionalArgs - Argumentos adicionales a loggear
3162
+ */
3163
+ writeOutput(message, level, styles, additionalArgs) {
3164
+ const mode = this.config.outputMode ?? "console";
3165
+ if (mode === "silent") return;
3166
+ if (mode === "custom" && this.config.outputWriter) {
3167
+ const fullMessage = additionalArgs.length > 0 ? `${message} ${additionalArgs.map((a) => String(a)).join(" ")}` : message;
3168
+ this.config.outputWriter.write(fullMessage, level, styles);
3169
+ return;
3170
+ }
3171
+ if (additionalArgs.length > 0) console.log(message, ...styles, ...additionalArgs);
3172
+ else console.log(message, ...styles);
3173
+ }
3174
+ /**
3175
+ * Procesador de comandos CLI para configuración y exportación del logger
3176
+ *
3177
+ * @param {string} command - Comando CLI a ejecutar
3178
+ * @returns {Promise<void>}
3179
+ *
3180
+ * @example
3181
+ * // Comandos disponibles
3182
+ * await logger.cli('export json'); // Exporta logs en JSON
3183
+ * await logger.cli('export csv'); // Exporta logs en CSV
3184
+ * await logger.cli('theme list'); // Lista temas disponibles
3185
+ * await logger.cli('theme set neon'); // Cambia al tema neon
3186
+ * await logger.cli('config show'); // Muestra configuración actual
3187
+ * await logger.cli('history clear'); // Limpia historial de logs
3188
+ * await logger.cli('status'); // Muestra estado del logger
3189
+ * await logger.cli('help'); // Muestra ayuda de comandos
3190
+ *
3191
+ */
3192
+ async cli(command) {
3193
+ if (!this.cliProcessor) {
3194
+ this.error("CLI processor not initialized");
3195
+ return;
3196
+ }
3197
+ await this.cliProcessor.processCommand(command, this);
3198
+ }
3199
+ };
3200
+ /**
3201
+ * Instancia singleton lazy — se inicializa en la primera llamada a
3202
+ * {@link getDefaultLogger}, no al importar el módulo.
3203
+ *
3204
+ * @private
3205
+ */
3206
+ let _defaultLogger = null;
3207
+ /**
3208
+ * Crea el singleton del Logger por defecto de forma lazy.
3209
+ *
3210
+ * El singleton se construye solo en la primera llamada, de modo que
3211
+ * importar el módulo nunca ejecuta `new Logger(...)` ni
3212
+ * `displayInitBanner()`. Así los imports del módulo quedan side-effect free.
3213
+ *
3214
+ * @returns La instancia compartida de Logger
3215
+ */
3216
+ function getDefaultLogger() {
3217
+ if (!_defaultLogger) {
3218
+ _defaultLogger = new Logger({
3219
+ verbosity: "info",
3220
+ enableColors: true,
3221
+ enableTimestamps: true,
3222
+ enableStackTrace: true,
3223
+ cliLevel: "normal"
3224
+ });
3225
+ try {
3226
+ if (typeof window !== "undefined" || typeof document !== "undefined") displayInitBanner();
3227
+ } catch {}
3228
+ }
3229
+ return _defaultLogger;
3230
+ }
3231
+ new Proxy({}, { get(_target, prop, receiver) {
3232
+ const instance = getDefaultLogger();
3233
+ const value = Reflect.get(instance, prop, receiver);
3234
+ return typeof value === "function" ? value.bind(instance) : value;
3235
+ } });
3236
+ /**
3237
+ * Estrecha un contexto free-form `Record<string, unknown>` a un bag tipado
3238
+ * `ILogAttributes`. Los shapes desconocidos caen a strings JSON-encoded,
3239
+ * lo que mantiene conforme al transport OTLP (cada valor cae en un slot tipado).
3240
+ *
3241
+ * @param input - Contexto suministrado por el usuario (típicamente `Logger.context`).
3242
+ * @returns Un nuevo bag de attributes que satisface `ILogAttributes`.
3243
+ */
3244
+ function toLogAttributes(input) {
3245
+ const out = {};
3246
+ for (const [key, value] of Object.entries(input)) {
3247
+ const mapped = toAttributeValue(value);
3248
+ if (mapped !== void 0) out[key] = mapped;
3249
+ }
3250
+ return out;
3251
+ }
3252
+ function toAttributeValue(value) {
3253
+ if (value === null || value === void 0) return void 0;
3254
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
3255
+ if (Array.isArray(value)) {
3256
+ const values = [];
3257
+ for (const item of value) {
3258
+ const mapped = toAttributeValue(item);
3259
+ if (mapped !== void 0) values.push(mapped);
3260
+ }
3261
+ return values;
3262
+ }
3263
+ try {
3264
+ return JSON.stringify(value);
3265
+ } catch {
3266
+ return;
3267
+ }
3268
+ }
3269
+ //#endregion
3270
+ //#region src/index.ts
3271
+ /**
3272
+ * @fileoverview Better Logger — default entry point.
3273
+ *
3274
+ * Re-exports `Logger`, the scoped loggers, subpath-style bridges, and
3275
+ * cross-runtime styling/utility helpers. Side-effect free at import.
3276
+ */
3277
+ let _logger = null;
3278
+ function getLogger() {
3279
+ if (!_logger) _logger = new Logger();
3280
+ return _logger;
3281
+ }
3282
+ /**
3283
+ * Default Logger singleton (lazy). Use this for the common case.
3284
+ */
3285
+ var src_default = getLogger();
3286
+ /**
3287
+ * Top-level log methods bound to the default singleton.
3288
+ */
3289
+ const debug = (...args) => getLogger().debug(...args);
3290
+ const info = (...args) => getLogger().info(...args);
3291
+ const warn = (...args) => getLogger().warn(...args);
3292
+ const error = (...args) => getLogger().error(...args);
3293
+ const success = (...args) => getLogger().success(...args);
3294
+ const critical = (...args) => getLogger().critical(...args);
3295
+ const trace = (...args) => getLogger().trace(...args);
3296
+ const table = (data, columns) => getLogger().table(data, columns);
3297
+ const group = (label, collapsed) => getLogger().group(label, collapsed);
3298
+ const groupEnd = () => getLogger().groupEnd();
3299
+ const time = (label) => getLogger().time(label);
3300
+ const timeEnd = (label) => getLogger().timeEnd(label);
3301
+ const setGlobalPrefix = (prefix) => getLogger().setGlobalPrefix(prefix);
3302
+ const scope = (name) => getLogger().scope(name);
3303
+ const component = (name) => getLogger().component(name);
3304
+ const api = (name) => getLogger().api(name);
3305
+ const badges = (badgeList) => getLogger().badges(badgeList);
3306
+ const badge = (badgeName) => getLogger().badge(badgeName);
3307
+ const clearBadges = () => getLogger().clearBadges();
3308
+ const setVerbosity = (level) => getLogger().setVerbosity(level);
3309
+ const addHandler = (handler) => getLogger().addHandler(handler);
3310
+ const setTheme = (theme) => getLogger().setTheme(theme);
3311
+ const setBannerType = (bannerType) => getLogger().setBannerType(bannerType);
3312
+ const showBanner = (bannerType) => getLogger().showBanner(bannerType);
3313
+ const logWithSVG = (message, svgContent, options) => getLogger().logWithSVG(message, svgContent, options);
3314
+ const logAnimated = (message, duration) => getLogger().logAnimated(message, duration);
3315
+ const cli = (command) => getLogger().cli(command);
3316
+ const addSerializer = (type, serializer, priority) => getLogger().addSerializer(type, serializer, priority);
3317
+ const removeSerializer = (type) => getLogger().removeSerializer(type);
3318
+ const on = (event, callback, priority) => getLogger().on(event, callback, priority);
3319
+ const once = (event, callback, priority) => getLogger().once(event, callback, priority);
3320
+ const off = (event, callback) => getLogger().off(event, callback);
3321
+ const use = (middleware, priority) => getLogger().use(middleware, priority);
3322
+ const addTransport = (target) => getLogger().addTransport(target);
3323
+ const removeTransport = (id) => getLogger().removeTransport(id);
3324
+ const flushTransports = () => getLogger().flushTransports();
3325
+ const closeTransports = () => getLogger().closeTransports();
3326
+ //#endregion
3327
+ export { APILogger, BANNER_VARIANTS, ComponentLogger, ContextLogger, DEFAULT_CONFIG, Logger, ScopedLogger, StyleBuilder, StylePresets, THEME_BANNERS, THEME_PRESETS, addHandler, addSerializer, addTransport, ansiBackground, ansiBold, ansiColor, ansiDim, ansiStyle, ansiUnderline, api, badge, badges, clearBadges, cli, closeTransports, component, createLogEntry, critical, debug, src_default as default, error, flushTransports, formatLogLevelANSI, formatSuccessANSI, formatTablePlain, formatTimestamp, getColorCapability, getConsoleMethod, getEnvironment, getEnvironmentInfo, getTerminalHeight, getTerminalWidth, group, groupEnd, info, isRunningInTerminal, logAnimated, logWithSVG, off, on, once, parseStackTrace, removeSerializer, removeTransport, safeSerialize, scope, setBannerType, setGlobalPrefix, setTheme, setVerbosity, showBanner, success, supportsANSI, table, time, timeEnd, trace, use, warn };
3328
+
3329
+ //# sourceMappingURL=index.js.map