@mks2508/better-logger 5.0.1 → 5.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/dist/Logger.d.ts +976 -0
  2. package/dist/Logger.d.ts.map +1 -0
  3. package/dist/ScopedLogger.d.ts +74 -0
  4. package/dist/ScopedLogger.d.ts.map +1 -0
  5. package/dist/chunks/Logger-CKqzXDh3.js +2 -0
  6. package/dist/chunks/Logger-CKqzXDh3.js.map +1 -0
  7. package/dist/chunks/Logger-D_vuKP4l.js +4511 -0
  8. package/dist/chunks/Logger-D_vuKP4l.js.map +1 -0
  9. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js +33 -0
  10. package/dist/chunks/RemoteLogHandler-CjWpWZGl.js.map +1 -0
  11. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js +2 -0
  12. package/dist/chunks/RemoteLogHandler-ymkQ97xl.js.map +1 -0
  13. package/dist/chunks/cli-module-B-njrTWb.js +2 -0
  14. package/dist/chunks/cli-module-B-njrTWb.js.map +1 -0
  15. package/dist/chunks/cli-module-Cx7qotPY.js +390 -0
  16. package/dist/chunks/cli-module-Cx7qotPY.js.map +1 -0
  17. package/dist/chunks/color-converter-CCSQRztd.js +2 -0
  18. package/dist/chunks/color-converter-CCSQRztd.js.map +1 -0
  19. package/dist/chunks/color-converter-_Xdmsy7E.js +462 -0
  20. package/dist/chunks/color-converter-_Xdmsy7E.js.map +1 -0
  21. package/dist/chunks/environment-C1xxvc8l.js +1127 -0
  22. package/dist/chunks/environment-C1xxvc8l.js.map +1 -0
  23. package/dist/chunks/environment-Cprkw3g9.js +4 -0
  24. package/dist/chunks/environment-Cprkw3g9.js.map +1 -0
  25. package/dist/chunks/formatting-DMJxYq9o.js +380 -0
  26. package/dist/chunks/formatting-DMJxYq9o.js.map +1 -0
  27. package/dist/chunks/formatting-DpKxCsXq.js +2 -0
  28. package/dist/chunks/formatting-DpKxCsXq.js.map +1 -0
  29. package/dist/cli/CommandProcessor.d.ts +100 -0
  30. package/dist/cli/CommandProcessor.d.ts.map +1 -0
  31. package/dist/cli/commands/ConfigCommand.d.ts +14 -0
  32. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -0
  33. package/dist/cli/commands/ExportCommand.d.ts +48 -0
  34. package/dist/cli/commands/ExportCommand.d.ts.map +1 -0
  35. package/dist/cli/commands/HistoryCommand.d.ts +47 -0
  36. package/dist/cli/commands/HistoryCommand.d.ts.map +1 -0
  37. package/dist/cli/commands/StatusCommand.d.ts +30 -0
  38. package/dist/cli/commands/StatusCommand.d.ts.map +1 -0
  39. package/dist/cli/commands/ThemeCommand.d.ts +30 -0
  40. package/dist/cli/commands/ThemeCommand.d.ts.map +1 -0
  41. package/dist/cli/help.d.ts +12 -0
  42. package/dist/cli/help.d.ts.map +1 -0
  43. package/dist/cli/index.d.ts +15 -0
  44. package/dist/cli/index.d.ts.map +1 -0
  45. package/{src/cli-module.ts → dist/cli-module.d.ts} +2 -8
  46. package/dist/cli-module.d.ts.map +1 -0
  47. package/dist/cli-primitives/box.d.ts +11 -0
  48. package/dist/cli-primitives/box.d.ts.map +1 -0
  49. package/dist/cli-primitives/cli-table.d.ts +11 -0
  50. package/dist/cli-primitives/cli-table.d.ts.map +1 -0
  51. package/dist/cli-primitives/divider.d.ts +11 -0
  52. package/dist/cli-primitives/divider.d.ts.map +1 -0
  53. package/dist/cli-primitives/header.d.ts +12 -0
  54. package/dist/cli-primitives/header.d.ts.map +1 -0
  55. package/{src/cli-primitives/index.ts → dist/cli-primitives/index.d.ts} +1 -1
  56. package/dist/cli-primitives/index.d.ts.map +1 -0
  57. package/dist/cli-primitives/server-fallback.d.ts +25 -0
  58. package/dist/cli-primitives/server-fallback.d.ts.map +1 -0
  59. package/dist/cli-primitives/spinner.d.ts +47 -0
  60. package/dist/cli-primitives/spinner.d.ts.map +1 -0
  61. package/dist/cli-primitives/step.d.ts +11 -0
  62. package/dist/cli-primitives/step.d.ts.map +1 -0
  63. package/dist/cli.cjs +2 -0
  64. package/dist/cli.cjs.map +1 -0
  65. package/dist/cli.js +12 -0
  66. package/dist/cli.js.map +1 -0
  67. package/dist/constants.d.ts +235 -0
  68. package/dist/constants.d.ts.map +1 -0
  69. package/dist/core.cjs +2 -0
  70. package/dist/core.cjs.map +1 -0
  71. package/dist/core.d.ts +127 -0
  72. package/dist/core.d.ts.map +1 -0
  73. package/dist/core.js +291 -0
  74. package/dist/core.js.map +1 -0
  75. package/dist/example.d.ts +18 -0
  76. package/dist/example.d.ts.map +1 -0
  77. package/dist/exports-module.d.ts +196 -0
  78. package/dist/exports-module.d.ts.map +1 -0
  79. package/dist/exports.cjs +2 -0
  80. package/dist/exports.cjs.map +1 -0
  81. package/dist/exports.js +238 -0
  82. package/dist/exports.js.map +1 -0
  83. package/dist/handlers/AnalyticsLogHandler.d.ts +8 -0
  84. package/dist/handlers/AnalyticsLogHandler.d.ts.map +1 -0
  85. package/dist/handlers/ExportLogHandler.d.ts +100 -0
  86. package/dist/handlers/ExportLogHandler.d.ts.map +1 -0
  87. package/dist/handlers/FileLogHandler.d.ts +33 -0
  88. package/dist/handlers/FileLogHandler.d.ts.map +1 -0
  89. package/dist/handlers/RemoteLogHandler.d.ts +11 -0
  90. package/dist/handlers/RemoteLogHandler.d.ts.map +1 -0
  91. package/{src/handlers/index.ts → dist/handlers/index.d.ts} +2 -2
  92. package/dist/handlers/index.d.ts.map +1 -0
  93. package/dist/hooks/HookManager.d.ts +21 -0
  94. package/dist/hooks/HookManager.d.ts.map +1 -0
  95. package/{src/hooks/index.ts → dist/hooks/index.d.ts} +1 -0
  96. package/dist/hooks/index.d.ts.map +1 -0
  97. package/dist/index.cjs +2 -0
  98. package/dist/index.cjs.map +1 -0
  99. package/dist/index.d.ts +161 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +627 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/main.d.ts +2 -0
  104. package/dist/main.d.ts.map +1 -0
  105. package/dist/serializers/SerializerRegistry.d.ts +16 -0
  106. package/dist/serializers/SerializerRegistry.d.ts.map +1 -0
  107. package/{src/serializers/index.ts → dist/serializers/index.d.ts} +1 -0
  108. package/dist/serializers/index.d.ts.map +1 -0
  109. package/dist/styling/LogStyleBuilder.d.ts +146 -0
  110. package/dist/styling/LogStyleBuilder.d.ts.map +1 -0
  111. package/dist/styling/SemanticStyles.d.ts +178 -0
  112. package/dist/styling/SemanticStyles.d.ts.map +1 -0
  113. package/dist/styling/SmartPresets.d.ts +22 -0
  114. package/dist/styling/SmartPresets.d.ts.map +1 -0
  115. package/dist/styling/StyleBuilder.d.ts +140 -0
  116. package/dist/styling/StyleBuilder.d.ts.map +1 -0
  117. package/dist/styling/StyleCache.d.ts +42 -0
  118. package/dist/styling/StyleCache.d.ts.map +1 -0
  119. package/dist/styling/banners.d.ts +42 -0
  120. package/dist/styling/banners.d.ts.map +1 -0
  121. package/dist/styling/index.d.ts +10 -0
  122. package/dist/styling/index.d.ts.map +1 -0
  123. package/dist/styling/themes.d.ts +7 -0
  124. package/dist/styling/themes.d.ts.map +1 -0
  125. package/dist/styling-module.d.ts +178 -0
  126. package/dist/styling-module.d.ts.map +1 -0
  127. package/dist/styling.cjs +2 -0
  128. package/dist/styling.cjs.map +1 -0
  129. package/dist/styling.js +146 -0
  130. package/dist/styling.js.map +1 -0
  131. package/dist/terminal/color-converter.d.ts +73 -0
  132. package/dist/terminal/color-converter.d.ts.map +1 -0
  133. package/dist/terminal/formatter.d.ts +20 -0
  134. package/dist/terminal/formatter.d.ts.map +1 -0
  135. package/dist/terminal/terminal-renderer.d.ts +77 -0
  136. package/dist/terminal/terminal-renderer.d.ts.map +1 -0
  137. package/dist/transports/ConsoleTransport.d.ts +9 -0
  138. package/dist/transports/ConsoleTransport.d.ts.map +1 -0
  139. package/dist/transports/FileTransport.d.ts +15 -0
  140. package/dist/transports/FileTransport.d.ts.map +1 -0
  141. package/dist/transports/HttpTransport.d.ts +16 -0
  142. package/dist/transports/HttpTransport.d.ts.map +1 -0
  143. package/dist/transports/TransportManager.d.ts +14 -0
  144. package/dist/transports/TransportManager.d.ts.map +1 -0
  145. package/{src/transports/index.ts → dist/transports/index.d.ts} +1 -0
  146. package/dist/transports/index.d.ts.map +1 -0
  147. package/{src/types/core.ts → dist/types/core.d.ts} +25 -62
  148. package/dist/types/core.d.ts.map +1 -0
  149. package/{src/types/handlers.ts → dist/types/handlers.d.ts} +5 -15
  150. package/dist/types/handlers.d.ts.map +1 -0
  151. package/{src/types/hooks.ts → dist/types/hooks.d.ts} +3 -12
  152. package/dist/types/hooks.d.ts.map +1 -0
  153. package/dist/types/index.d.ts +11 -0
  154. package/dist/types/index.d.ts.map +1 -0
  155. package/{src/types/serializers.ts → dist/types/serializers.d.ts} +1 -6
  156. package/dist/types/serializers.d.ts.map +1 -0
  157. package/{src/types/transports.ts → dist/types/transports.d.ts} +2 -7
  158. package/dist/types/transports.d.ts.map +1 -0
  159. package/dist/utils/adapter.d.ts +48 -0
  160. package/dist/utils/adapter.d.ts.map +1 -0
  161. package/dist/utils/ansi-colors.d.ts +156 -0
  162. package/dist/utils/ansi-colors.d.ts.map +1 -0
  163. package/dist/utils/environment-detector.d.ts +45 -0
  164. package/dist/utils/environment-detector.d.ts.map +1 -0
  165. package/dist/utils/environment.d.ts +47 -0
  166. package/dist/utils/environment.d.ts.map +1 -0
  167. package/dist/utils/formatting.d.ts +58 -0
  168. package/dist/utils/formatting.d.ts.map +1 -0
  169. package/dist/utils/index.d.ts +8 -0
  170. package/dist/utils/index.d.ts.map +1 -0
  171. package/dist/utils/opentui-detection.d.ts +34 -0
  172. package/dist/utils/opentui-detection.d.ts.map +1 -0
  173. package/dist/utils/output.d.ts +46 -0
  174. package/dist/utils/output.d.ts.map +1 -0
  175. package/dist/utils/stackTrace.d.ts +6 -0
  176. package/dist/utils/stackTrace.d.ts.map +1 -0
  177. package/dist/utils/timestamps.d.ts +20 -0
  178. package/dist/utils/timestamps.d.ts.map +1 -0
  179. package/{src/writers/BufferWriter.ts → dist/writers/BufferWriter.d.ts} +16 -77
  180. package/dist/writers/BufferWriter.d.ts.map +1 -0
  181. package/{src/writers/index.ts → dist/writers/index.d.ts} +1 -1
  182. package/dist/writers/index.d.ts.map +1 -0
  183. package/package.json +5 -1
  184. package/.claude/settings.local.json +0 -48
  185. package/.github/workflows/ci-quality.yml +0 -357
  186. package/.github/workflows/docs-demo.yml +0 -119
  187. package/.github/workflows/releases-core.yml +0 -512
  188. package/.github/workflows/releases-full.yml +0 -582
  189. package/.github/workflows-backup/ci.yml +0 -221
  190. package/.github/workflows-backup/nightly.yml +0 -196
  191. package/.github/workflows-backup/release-optimized.yml +0 -373
  192. package/.github/workflows-backup/release.yml +0 -269
  193. package/.release-notes-0.2.0.md +0 -129
  194. package/.yamllint +0 -28
  195. package/CHANGELOG.json +0 -1120
  196. package/CHANGELOG.md +0 -209
  197. package/CLAUDE.md +0 -217
  198. package/demo.html +0 -847
  199. package/docs/API.md +0 -918
  200. package/docs/CORE.md +0 -264
  201. package/docs/DEVELOPMENT.md +0 -731
  202. package/docs/EXPORTS.md +0 -467
  203. package/docs/PACKAGES.md +0 -244
  204. package/docs/STYLING.md +0 -405
  205. package/docs/_config.yml +0 -36
  206. package/docs/index.md +0 -179
  207. package/examples/README.md +0 -208
  208. package/examples/basic-logging.js +0 -75
  209. package/examples/data-export.js +0 -234
  210. package/examples/package.json +0 -16
  211. package/examples/performance-timing.js +0 -170
  212. package/examples/simplified-api.js +0 -124
  213. package/examples/styling-themes.js +0 -207
  214. package/index.html +0 -358
  215. package/packages/core/package.json +0 -57
  216. package/packages/exports/package.json +0 -41
  217. package/packages/nodejs-opentui/README.md +0 -232
  218. package/packages/nodejs-opentui/package.json +0 -72
  219. package/packages/nodejs-opentui/src/LogRenderer.ts +0 -171
  220. package/packages/nodejs-opentui/src/OpenTUILogHandler.ts +0 -178
  221. package/packages/nodejs-opentui/src/components/LogBadge.tsx +0 -131
  222. package/packages/nodejs-opentui/src/index.ts +0 -133
  223. package/packages/nodejs-opentui/src/types.ts +0 -158
  224. package/packages/nodejs-opentui/tsconfig.json +0 -20
  225. package/packages/styling/package.json +0 -41
  226. package/playground/demo-all.ts +0 -95
  227. package/playground/demo-box.ts +0 -85
  228. package/playground/demo-levels.ts +0 -56
  229. package/playground/demo-real-world.ts +0 -98
  230. package/playground/demo-spinner.ts +0 -77
  231. package/playground/demo-steps.ts +0 -72
  232. package/playground/demo-table.ts +0 -83
  233. package/project-utils/README.md +0 -172
  234. package/project-utils/auto-release-gemini.ts +0 -1193
  235. package/project-utils/auto-release-ui.ts +0 -1329
  236. package/project-utils/commit-generator.ts +0 -1385
  237. package/project-utils/commit-ui.ts +0 -264
  238. package/project-utils/git-utils.ts +0 -199
  239. package/project-utils/github-release-manager.ts +0 -466
  240. package/project-utils/project-config.ts +0 -260
  241. package/project-utils/prompt-templates.js +0 -345
  242. package/project-utils/prompt-templates.ts +0 -422
  243. package/project-utils/version-manager.ts +0 -1078
  244. package/src/Logger.ts +0 -1858
  245. package/src/ScopedLogger.ts +0 -256
  246. package/src/cli/CommandProcessor.ts +0 -248
  247. package/src/cli/commands/ConfigCommand.ts +0 -93
  248. package/src/cli/commands/ExportCommand.ts +0 -276
  249. package/src/cli/commands/HistoryCommand.ts +0 -117
  250. package/src/cli/commands/StatusCommand.ts +0 -112
  251. package/src/cli/commands/ThemeCommand.ts +0 -88
  252. package/src/cli/help.ts +0 -127
  253. package/src/cli/index.ts +0 -71
  254. package/src/cli-primitives/box.ts +0 -86
  255. package/src/cli-primitives/cli-table.ts +0 -62
  256. package/src/cli-primitives/divider.ts +0 -17
  257. package/src/cli-primitives/header.ts +0 -18
  258. package/src/cli-primitives/server-fallback.ts +0 -54
  259. package/src/cli-primitives/spinner.ts +0 -133
  260. package/src/cli-primitives/step.ts +0 -22
  261. package/src/constants.ts +0 -313
  262. package/src/core.ts +0 -397
  263. package/src/example.ts +0 -210
  264. package/src/exports-module.ts +0 -311
  265. package/src/handlers/AnalyticsLogHandler.ts +0 -22
  266. package/src/handlers/ExportLogHandler.ts +0 -610
  267. package/src/handlers/FileLogHandler.ts +0 -169
  268. package/src/handlers/RemoteLogHandler.ts +0 -42
  269. package/src/hooks/HookManager.ts +0 -177
  270. package/src/index.ts +0 -395
  271. package/src/main.ts +0 -196
  272. package/src/serializers/SerializerRegistry.ts +0 -173
  273. package/src/style.css +0 -96
  274. package/src/styling/LogStyleBuilder.ts +0 -355
  275. package/src/styling/SemanticStyles.ts +0 -380
  276. package/src/styling/SmartPresets.ts +0 -288
  277. package/src/styling/StyleBuilder.ts +0 -319
  278. package/src/styling/StyleCache.ts +0 -131
  279. package/src/styling/banners.ts +0 -168
  280. package/src/styling/index.ts +0 -27
  281. package/src/styling/themes.ts +0 -235
  282. package/src/styling-module.ts +0 -244
  283. package/src/terminal/color-converter.ts +0 -315
  284. package/src/terminal/formatter.ts +0 -242
  285. package/src/terminal/terminal-renderer.ts +0 -342
  286. package/src/transports/ConsoleTransport.ts +0 -28
  287. package/src/transports/FileTransport.ts +0 -53
  288. package/src/transports/HttpTransport.ts +0 -56
  289. package/src/transports/TransportManager.ts +0 -130
  290. package/src/types/index.ts +0 -83
  291. package/src/typescript.svg +0 -1
  292. package/src/utils/adapter.ts +0 -291
  293. package/src/utils/ansi-colors.ts +0 -333
  294. package/src/utils/environment-detector.ts +0 -170
  295. package/src/utils/environment.ts +0 -94
  296. package/src/utils/formatting.ts +0 -332
  297. package/src/utils/index.ts +0 -33
  298. package/src/utils/opentui-detection.ts +0 -138
  299. package/src/utils/output.ts +0 -227
  300. package/src/utils/stackTrace.ts +0 -144
  301. package/src/utils/timestamps.ts +0 -80
  302. package/src/vite-env.d.ts +0 -1
  303. package/test-core-browser.html +0 -237
  304. package/test-core-node.js +0 -63
  305. package/tests/test-conflict-resolution.ts +0 -391
  306. package/tests/validate-workflows.sh +0 -131
  307. package/tests/yaml-autofix.sh +0 -146
  308. package/tsconfig.json +0 -50
  309. package/vite.config.ts +0 -256
  310. /package/{public → dist}/vite.svg +0 -0
package/src/Logger.ts DELETED
@@ -1,1858 +0,0 @@
1
- /**
2
- * @fileoverview Logger avanzado con arquitectura modular y API simplificada
3
- * @version 0.3.0
4
- * @since 2024
5
- *
6
- * Sistema de logging profesional con estilos CSS avanzados, temas adaptativos,
7
- * badges automáticos, contextos temporales y exportación de datos.
8
- */
9
-
10
- // Type imports
11
- import type {
12
- LogLevel,
13
- Verbosity,
14
- ThemeVariant,
15
- BannerType,
16
- LoggerConfig,
17
- TimerEntry,
18
- ILogHandler,
19
- LogMetadata,
20
- StyleOptions,
21
- Bindings,
22
- SerializerFn,
23
- HookEvent,
24
- HookCallback,
25
- MiddlewareFn,
26
- TransportTarget,
27
- TransportRecord
28
- } from './types/index.js';
29
-
30
- // Enterprise features
31
- import { SerializerRegistry } from './serializers/index.js';
32
- import { HookManager } from './hooks/index.js';
33
- import { TransportManager } from './transports/index.js';
34
-
35
- // Utility imports
36
- import { parseStackTrace } from './utils/stackTrace.js';
37
- import { formatTimestamp } from './utils/timestamps.js';
38
- import { createStyledOutput, setupThemeChangeListener } from './utils/output.js';
39
- import { getEnvironment, getColorCapability, isRunningInTerminal } from './utils/environment-detector.js';
40
- import { formatBadge } from './terminal/formatter.js';
41
-
42
- // Styling imports
43
- import {
44
- THEME_PRESETS,
45
- THEME_BANNERS,
46
- displayInitBanner,
47
- StylePresets,
48
- StyleBuilder
49
- } from './styling/index.js';
50
-
51
- // Smart presets and dynamic scoped loggers
52
- import { getSmartPreset, getAvailablePresets, hasPreset } from './styling/SmartPresets.js';
53
- import { createLogStyleBuilder } from './styling/LogStyleBuilder.js';
54
-
55
- // Scoped loggers (static import for performance)
56
- import { ScopedLogger, APILogger, ComponentLogger } from './ScopedLogger.js';
57
-
58
- // Handler imports
59
- import { ExportLogHandler } from './handlers/index.js';
60
-
61
- // CLI imports
62
- import { createDefaultCLI, type CommandProcessor } from './cli/index.js';
63
-
64
- // Constants
65
- import { DEFAULT_CONFIG, CLI_LEVEL_MAP } from './constants.js';
66
-
67
- // CLI Primitives
68
- import type { CLILogLevel, ISpinnerHandle, IBoxOptions, ITableOptions } from './types/index.js';
69
- import { renderStep } from './cli-primitives/step.js';
70
- import { renderHeader } from './cli-primitives/header.js';
71
- import { renderDivider } from './cli-primitives/divider.js';
72
- import { renderBox } from './cli-primitives/box.js';
73
- import { renderTable } from './cli-primitives/cli-table.js';
74
- import { SpinnerManager, NoopSpinner } from './cli-primitives/spinner.js';
75
- import { ServerFallback } from './cli-primitives/server-fallback.js';
76
-
77
- /**
78
- * Estilos del tema activo actual
79
- * @private
80
- */
81
- let LEVEL_STYLES = THEME_PRESETS.default;
82
-
83
- /**
84
- * Clase principal Logger con capacidades avanzadas de logging
85
- *
86
- * @class Logger
87
- * @description Sistema completo de logging con temas, badges, contextos y exportación.
88
- * Detecta automáticamente el tema claro/oscuro del navegador.
89
- *
90
- * @example
91
- * // Uso básico sin configuración
92
- * import logger from '@mks2508/better-logger';
93
- * logger.info('Aplicación iniciada');
94
- * logger.success('Conexión establecida');
95
- *
96
- * @example
97
- * // Aplicar un preset temático
98
- * logger.preset('cyberpunk');
99
- * logger.warn('Advertencia con estilo neón');
100
- *
101
- * @example
102
- * // Logger con scope para componentes
103
- * const auth = logger.component('Autenticación');
104
- * auth.info('Usuario intentando login');
105
- * auth.success('Login exitoso');
106
- *
107
- * @since 0.3.0
108
- */
109
- export class Logger {
110
- private config: LoggerConfig;
111
- private scopedPrefix?: string;
112
- private handlers: ILogHandler[] = [];
113
- private timers: Map<string, TimerEntry> = new Map();
114
- private groupDepth: number = 0;
115
- private exportHandler?: ExportLogHandler;
116
- private cliProcessor?: CommandProcessor;
117
- private themeChangeListener?: (() => void) | null;
118
- private badgeList: string[] = [];
119
- private displaySettings = {
120
- showTimestamp: true,
121
- showLocation: true,
122
- showBadges: true
123
- };
124
-
125
- private serializerRegistry: SerializerRegistry;
126
- private hookManager: HookManager;
127
- private transportManager?: TransportManager;
128
-
129
- /** Whether CLI primitives (step, box, header, etc.) should be shown @since 5.0.0 */
130
- private _showPrimitives = true;
131
- /** Server-mode fallback for non-TTY environments @since 5.0.0 */
132
- private _serverFallback?: ServerFallback;
133
-
134
- /**
135
- * Crea una nueva instancia del Logger
136
- *
137
- * @param {Partial<LoggerConfig>} config - Configuración opcional del logger
138
- *
139
- * @example
140
- * // Logger con configuración personalizada
141
- * const logger = new Logger({
142
- * theme: 'neon',
143
- * globalPrefix: 'MiApp',
144
- * verbosity: 'debug',
145
- * bufferSize: 1000
146
- * });
147
- */
148
- constructor(config: Partial<LoggerConfig> = {}) {
149
- this.config = {
150
- ...DEFAULT_CONFIG,
151
- ...config,
152
- };
153
-
154
- // Initialize enterprise features
155
- this.serializerRegistry = new SerializerRegistry();
156
- this.hookManager = new HookManager();
157
-
158
- // Initialize export handler if buffer size is specified
159
- if (this.config.bufferSize) {
160
- this.exportHandler = new ExportLogHandler(this.config.bufferSize);
161
- this.handlers.push(this.exportHandler);
162
- }
163
-
164
- // Initialize CLI processor
165
- this.cliProcessor = createDefaultCLI();
166
-
167
- // Set up theme change listener if auto-detection is enabled
168
- if (this.config.autoDetectTheme) {
169
- this.setupAutoThemeDetection();
170
- }
171
- }
172
-
173
- // ===== PRIVATE HELPER METHODS =====
174
-
175
- /**
176
- * Configura la detección automática de tema con listener de cambios
177
- * @private
178
- * @description Detecta automáticamente si el navegador está en modo claro u oscuro
179
- */
180
- private setupAutoThemeDetection(): void {
181
- // Clean up existing listener if any
182
- if (this.themeChangeListener) {
183
- this.themeChangeListener();
184
- this.themeChangeListener = null;
185
- }
186
-
187
- // Set up new listener
188
- this.themeChangeListener = setupThemeChangeListener((theme) => {
189
- // Theme changed - logs will automatically use new colors on next call
190
- // No need to update anything as colors are resolved dynamically
191
- this.debug(`DevTools theme changed to: ${theme}`);
192
- });
193
- }
194
-
195
- // ===== CONFIGURATION METHODS =====
196
-
197
- /**
198
- * Obtiene la configuración actual del logger
199
- *
200
- * @returns {LoggerConfig} Configuración completa actual
201
- *
202
- * @example
203
- * const config = logger.getConfig();
204
- * console.log('Verbosidad actual:', config.verbosity);
205
- * console.log('Tema actual:', config.theme);
206
- *
207
- * @since 0.3.0
208
- */
209
- getConfig(): LoggerConfig {
210
- return { ...this.config };
211
- }
212
-
213
- /**
214
- * Actualiza la configuración del logger
215
- *
216
- * @param {Partial<LoggerConfig>} updates - Propiedades a actualizar
217
- *
218
- * @example
219
- * logger.updateConfig({
220
- * verbosity: 'debug',
221
- * enableTimestamps: false,
222
- * theme: 'cyberpunk'
223
- * });
224
- *
225
- * @since 0.3.0
226
- */
227
- updateConfig(updates: Partial<LoggerConfig>): void {
228
- const previousAutoDetect = this.config.autoDetectTheme;
229
- this.config = { ...this.config, ...updates };
230
-
231
- // Handle auto-detection changes
232
- if (updates.autoDetectTheme !== undefined && updates.autoDetectTheme !== previousAutoDetect) {
233
- if (updates.autoDetectTheme) {
234
- this.setupAutoThemeDetection();
235
- } else if (this.themeChangeListener) {
236
- this.themeChangeListener();
237
- this.themeChangeListener = null;
238
- }
239
- }
240
- }
241
-
242
- /**
243
- * Establece el prefijo global para todos los mensajes de log
244
- *
245
- * @param {string} prefix - Prefijo a usar
246
- *
247
- * @example
248
- * logger.setGlobalPrefix('MiApp');
249
- * logger.info('Iniciado'); // [MiApp] Iniciado
250
- *
251
- * @since 0.3.0
252
- */
253
- setGlobalPrefix(prefix: string): void {
254
- this.config.globalPrefix = prefix;
255
- }
256
-
257
- /**
258
- * Establece el nivel de verbosidad para filtrar la salida de logs
259
- *
260
- * @param {Verbosity} level - Nivel mínimo a mostrar ('debug' | 'info' | 'warn' | 'error' | 'critical' | 'silent')
261
- *
262
- * @example
263
- * logger.setVerbosity('warn'); // Solo muestra warn, error y critical
264
- * logger.setVerbosity('debug'); // Muestra todos los niveles
265
- * logger.setVerbosity('silent'); // No muestra nada
266
- *
267
- * @since 0.3.0
268
- */
269
- setVerbosity(level: Verbosity): void {
270
- this.config.verbosity = level;
271
- }
272
-
273
- /**
274
- * Establece el tema del logger
275
- *
276
- * @param {ThemeVariant} theme - Tema a aplicar ('default' | 'dark' | 'light' | 'neon' | 'minimal' | 'cyberpunk')
277
- *
278
- * @example
279
- * logger.setTheme('neon'); // Tema con colores neón
280
- * logger.setTheme('minimal'); // Tema minimalista
281
- * logger.setTheme('cyberpunk'); // Tema cyberpunk con efectos
282
- *
283
- * @since 0.3.0
284
- */
285
- setTheme(theme: ThemeVariant): void {
286
- // First check if it's a smart preset
287
- if (hasPreset(theme)) {
288
- this.preset(theme);
289
- return;
290
- }
291
-
292
- // Fallback to old theme system
293
- if (theme in THEME_PRESETS) {
294
- LEVEL_STYLES = (THEME_PRESETS as any)[theme];
295
- this.config.theme = theme;
296
-
297
- // Show theme-specific banner
298
- if (theme in THEME_BANNERS) {
299
- const themeBanner = (THEME_BANNERS as any)[theme];
300
- console.log(`%c${themeBanner.simple}`, themeBanner.style);
301
- }
302
-
303
- this.success(`Theme changed to: ${theme}`);
304
- } else {
305
- this.error(`Invalid theme: ${theme}. Available:`, [...getAvailablePresets(), ...Object.keys(THEME_PRESETS)]);
306
- }
307
- }
308
-
309
- /**
310
- * Establece el tipo de banner para mostrar en la inicialización
311
- *
312
- * @param {BannerType} bannerType - Tipo de banner ('simple' | 'ascii' | 'unicode' | 'svg' | 'animated')
313
- *
314
- * @example
315
- * logger.setBannerType('ascii'); // Banner con arte ASCII
316
- * logger.setBannerType('unicode'); // Banner con caracteres Unicode
317
- * logger.setBannerType('animated'); // Banner con animación
318
- *
319
- * @since 0.3.0
320
- */
321
- setBannerType(bannerType: BannerType): void {
322
- this.config.bannerType = bannerType;
323
- this.success(`Banner type changed to: ${bannerType}`);
324
- }
325
-
326
- /**
327
- * Reinicia el logger a la configuración por defecto
328
- *
329
- * @example
330
- * logger.resetConfig();
331
- * // Todo vuelve a la configuración inicial
332
- *
333
- * @since 0.3.0
334
- */
335
- resetConfig(): void {
336
- // Clean up theme listener
337
- if (this.themeChangeListener) {
338
- this.themeChangeListener();
339
- this.themeChangeListener = null;
340
- }
341
-
342
- this.config = { ...DEFAULT_CONFIG };
343
- LEVEL_STYLES = THEME_PRESETS.default;
344
-
345
- // Re-setup auto theme detection if enabled in default config
346
- if (this.config.autoDetectTheme) {
347
- this.setupAutoThemeDetection();
348
- }
349
-
350
- this.success('Logger configuration reset to defaults');
351
- }
352
-
353
- /**
354
- * Método de limpieza para eliminar listeners y liberar recursos
355
- *
356
- * @example
357
- * // Antes de cerrar la aplicación
358
- * logger.cleanup();
359
- *
360
- * @since 0.3.0
361
- */
362
- cleanup(): void {
363
- if (this.themeChangeListener) {
364
- this.themeChangeListener();
365
- this.themeChangeListener = null;
366
- }
367
- // Close transports
368
- this.transportManager?.close().catch(() => {});
369
- }
370
-
371
-
372
- // ===== SIMPLIFIED API =====
373
-
374
- /**
375
- * Aplica un preset inteligente - funciona perfectamente sin configuración
376
- *
377
- * @param {string} name - Nombre del preset a aplicar
378
- *
379
- * @example
380
- * // Presets disponibles
381
- * logger.preset('default'); // Limpio y adaptativo
382
- * logger.preset('cyberpunk'); // Colores neón, efectos brillantes
383
- * logger.preset('glassmorphism'); // Efectos de blur modernos
384
- * logger.preset('minimal'); // Minimalista y elegante
385
- * logger.preset('debug'); // Modo desarrollo detallado
386
- * logger.preset('production'); // Optimizado para producción
387
- *
388
- * @since 0.3.0
389
- */
390
- preset(name: string): void {
391
- if (!hasPreset(name)) {
392
- this.error(`Unknown preset: ${name}. Available presets:`, getAvailablePresets());
393
- return;
394
- }
395
-
396
- const presetConfig = getSmartPreset(name);
397
- if (presetConfig) {
398
- // Apply the smart preset configuration
399
- this.displaySettings.showTimestamp = presetConfig.timestamp?.show ?? true;
400
- this.displaySettings.showLocation = presetConfig.location?.show ?? true;
401
-
402
- // Store the preset config for use in createStyledOutput
403
- (this as any)._activePreset = presetConfig;
404
- (this as any)._activePresetName = name;
405
-
406
- // Only show success message in browser to avoid verbose terminal logs
407
- if (getEnvironment() === 'browser') {
408
- this.success(`Applied preset: ${name}`);
409
- }
410
- }
411
- }
412
-
413
- /**
414
- * Lista todos los presets disponibles
415
- *
416
- * @returns {string[]} Array con nombres de presets disponibles
417
- *
418
- * @example
419
- * const disponibles = logger.presets();
420
- * console.log(disponibles); // ['default', 'cyberpunk', 'glassmorphism', ...]
421
- *
422
- * @since 0.3.0
423
- */
424
- presets(): string[] {
425
- return getAvailablePresets();
426
- }
427
-
428
- // ===== TOGGLE METHODS =====
429
-
430
- /**
431
- * Oculta el timestamp en los logs
432
- *
433
- * @example
434
- * logger.hideTimestamp();
435
- * logger.info('Sin marca de tiempo'); // Sin timestamp visible
436
- *
437
- * @since 0.3.0
438
- */
439
- hideTimestamp(): this {
440
- this.displaySettings.showTimestamp = false;
441
- return this;
442
- }
443
-
444
- /**
445
- * Muestra el timestamp en los logs
446
- *
447
- * @example
448
- * logger.showTimestamp();
449
- * logger.info('Con marca de tiempo'); // [2024-01-15 10:30:45] Con marca de tiempo
450
- *
451
- * @since 0.3.0
452
- */
453
- showTimestamp(): this {
454
- this.displaySettings.showTimestamp = true;
455
- return this;
456
- }
457
-
458
- /**
459
- * Oculta la información de ubicación (archivo:línea) en los logs
460
- *
461
- * @example
462
- * logger.hideLocation();
463
- * logger.debug('Sin ubicación'); // Sin mostrar archivo:línea
464
- *
465
- * @since 0.3.0
466
- */
467
- hideLocation(): this {
468
- this.displaySettings.showLocation = false;
469
- return this;
470
- }
471
-
472
- /**
473
- * Muestra la información de ubicación (archivo:línea) en los logs
474
- *
475
- * @example
476
- * logger.showLocation();
477
- * logger.debug('Con ubicación'); // app.js:42 Con ubicación
478
- *
479
- * @since 0.3.0
480
- */
481
- showLocation(): this {
482
- this.displaySettings.showLocation = true;
483
- return this;
484
- }
485
-
486
- /**
487
- * Oculta los badges en los logs
488
- *
489
- * @example
490
- * logger.hideBadges();
491
- * const api = logger.api('REST');
492
- * api.info('Sin badges'); // Sin mostrar [API] [REST]
493
- *
494
- * @since 0.3.0
495
- */
496
- hideBadges(): this {
497
- this.displaySettings.showBadges = false;
498
- return this;
499
- }
500
-
501
- /**
502
- * Muestra los badges en los logs
503
- *
504
- * @example
505
- * logger.showBadges();
506
- * const api = logger.api('GraphQL');
507
- * api.info('Con badges'); // [API] [GraphQL] Con badges
508
- *
509
- * @since 0.3.0
510
- */
511
- showBadges(): this {
512
- this.displaySettings.showBadges = true;
513
- return this;
514
- }
515
-
516
- /**
517
- * Establece múltiples badges para los logs
518
- *
519
- * @param {string[]} badges - Array de badges a mostrar
520
- * @returns {this} Logger instance para encadenamiento
521
- *
522
- * @example
523
- * logger.badges(['v3', 'stable']).info('Release publicado');
524
- * logger.badges(['API', 'v2']).warn('Endpoint deprecado');
525
- *
526
- * @since 3.0.0
527
- */
528
- badges(badges: string[]): this {
529
- this.badgeList = [...badges];
530
- return this;
531
- }
532
-
533
- /**
534
- * Añade un badge individual a la lista
535
- *
536
- * @param {string} badge - Badge a añadir
537
- * @returns {this} Logger instance para encadenamiento
538
- *
539
- * @example
540
- * logger.badge('DEBUG').badge('AUTH').info('Token validado');
541
- *
542
- * @since 3.0.0
543
- */
544
- badge(badge: string): this {
545
- if (!this.badgeList.includes(badge)) {
546
- this.badgeList.push(badge);
547
- }
548
- return this;
549
- }
550
-
551
- /**
552
- * Limpia todos los badges activos
553
- *
554
- * @returns {this} Logger instance para encadenamiento
555
- *
556
- * @example
557
- * logger.clearBadges().info('Sin badges');
558
- *
559
- * @since 3.0.0
560
- */
561
- clearBadges(): this {
562
- this.badgeList = [];
563
- return this;
564
- }
565
-
566
- // ===== SCOPED LOGGERS =====
567
-
568
- component(name: string): ComponentLogger {
569
- return new ComponentLogger(this, name);
570
- }
571
-
572
- api(name: string): APILogger {
573
- return new APILogger(this, name);
574
- }
575
-
576
- scope(name: string): ScopedLogger {
577
- return new ScopedLogger(this, name);
578
- }
579
-
580
- // ===== SIMPLE CUSTOMIZATION =====
581
-
582
- /**
583
- * Personalización simple con configuración mínima
584
- *
585
- * @param {Object} overrides - Opciones de personalización
586
- * @param {Object} overrides.message - Configuración del mensaje
587
- * @param {Object} overrides.timestamp - Configuración del timestamp
588
- * @param {Object} overrides.location - Configuración de ubicación
589
- * @param {Object} overrides.level - Configuración del nivel
590
- * @param {Object} overrides.prefix - Configuración del prefijo
591
- * @param {string} overrides.spacing - Espaciado: 'compact' | 'normal' | 'spacious'
592
- *
593
- * @example
594
- * logger.customize({
595
- * message: { color: '#00ff00', size: '16px' },
596
- * timestamp: { show: false },
597
- * spacing: 'compact'
598
- * });
599
- *
600
- * @since 0.3.0
601
- */
602
- customize(overrides: {
603
- message?: { color?: string; font?: string; size?: string };
604
- timestamp?: { show?: boolean; color?: string };
605
- location?: { show?: boolean; color?: string };
606
- level?: { uppercase?: boolean; style?: string };
607
- prefix?: { show?: boolean; style?: string };
608
- spacing?: 'compact' | 'normal' | 'spacious';
609
- }): void {
610
- // Apply simple overrides
611
- if (overrides.timestamp?.show !== undefined) {
612
- this.displaySettings.showTimestamp = overrides.timestamp.show;
613
- }
614
- if (overrides.location?.show !== undefined) {
615
- this.displaySettings.showLocation = overrides.location.show;
616
- }
617
- if (overrides.prefix?.show !== undefined) {
618
- // Will be handled when we integrate with preset system
619
- }
620
-
621
- // Store customization for use in createStyledOutput
622
- (this as any)._customization = overrides;
623
- this.success('Customization applied');
624
- }
625
-
626
- /**
627
- * Access advanced styling API (for power users)
628
- */
629
- styles(): any {
630
- return createLogStyleBuilder(this);
631
- }
632
-
633
- // ===== HANDLER MANAGEMENT =====
634
-
635
- /**
636
- * Añade un handler personalizado para extender funcionalidad
637
- *
638
- * @param {ILogHandler} handler - Handler que implementa ILogHandler
639
- *
640
- * @example
641
- * // Handler personalizado para enviar logs a servidor
642
- * const remoteHandler = new RemoteLogHandler('https://api.ejemplo.com/logs');
643
- * logger.addHandler(remoteHandler);
644
- *
645
- * @example
646
- * // Handler para guardar en archivo
647
- * const fileHandler = new FileLogHandler('./app.log');
648
- * logger.addHandler(fileHandler);
649
- *
650
- * @since 0.3.0
651
- */
652
- addHandler(handler: ILogHandler): void {
653
- this.handlers.push(handler);
654
- }
655
-
656
- /**
657
- * Obtiene todos los handlers registrados
658
- *
659
- * @returns {ILogHandler[]} Array de handlers activos
660
- * @since 0.3.0
661
- */
662
- getHandlers(): ILogHandler[] {
663
- return [...this.handlers];
664
- }
665
-
666
- /**
667
- * Obtiene el handler de exportación si está disponible
668
- *
669
- * @returns {ExportLogHandler | undefined} Handler de exportación o undefined
670
- * @since 0.3.0
671
- */
672
- getExportHandler(): ExportLogHandler | undefined {
673
- return this.exportHandler;
674
- }
675
-
676
- // ===== SERIALIZERS =====
677
-
678
- /**
679
- * Añade un serializador personalizado para un tipo específico
680
- *
681
- * @param type - Constructor del tipo a serializar
682
- * @param serializer - Función de serialización
683
- * @param priority - Prioridad (mayor = primero)
684
- *
685
- * @example
686
- * logger.addSerializer(Error, (err) => ({
687
- * name: err.name,
688
- * message: err.message,
689
- * stack: err.stack?.split('\n').slice(0, 5)
690
- * }));
691
- *
692
- * @since 3.0.0
693
- */
694
- addSerializer<T>(
695
- type: new (...args: any[]) => T,
696
- serializer: SerializerFn<T>,
697
- priority?: number
698
- ): void {
699
- this.serializerRegistry.add(type, serializer, priority);
700
- }
701
-
702
- /**
703
- * Elimina un serializador registrado
704
- *
705
- * @param type - Constructor del tipo a remover
706
- * @returns true si se eliminó
707
- *
708
- * @since 3.0.0
709
- */
710
- removeSerializer<T>(type: new (...args: any[]) => T): boolean {
711
- return this.serializerRegistry.remove(type);
712
- }
713
-
714
- /**
715
- * Obtiene el registry de serializadores
716
- *
717
- * @returns SerializerRegistry
718
- * @since 3.0.0
719
- */
720
- getSerializerRegistry(): SerializerRegistry {
721
- return this.serializerRegistry;
722
- }
723
-
724
- // ===== HOOKS & MIDDLEWARE =====
725
-
726
- /**
727
- * Registra un hook para un evento
728
- *
729
- * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
730
- * @param callback - Función a ejecutar
731
- * @param priority - Prioridad (mayor = primero)
732
- * @returns Función para desregistrar
733
- *
734
- * @example
735
- * const unsubscribe = logger.on('beforeLog', (entry) => {
736
- * entry.correlationId = getCorrelationId();
737
- * return entry;
738
- * });
739
- *
740
- * @since 3.0.0
741
- */
742
- on(event: HookEvent, callback: HookCallback, priority?: number): () => void {
743
- return this.hookManager.on(event, callback, priority);
744
- }
745
-
746
- /**
747
- * Registra un hook que se ejecuta solo una vez
748
- *
749
- * @param event - Evento: 'beforeLog' | 'afterLog' | 'onError'
750
- * @param callback - Función a ejecutar
751
- * @param priority - Prioridad (mayor = primero)
752
- * @returns Función para desregistrar
753
- *
754
- * @since 3.0.0
755
- */
756
- once(event: HookEvent, callback: HookCallback, priority?: number): () => void {
757
- return this.hookManager.once(event, callback, priority);
758
- }
759
-
760
- /**
761
- * Elimina un hook registrado
762
- *
763
- * @param event - Evento del hook
764
- * @param callback - Callback a remover
765
- * @returns true si se eliminó
766
- *
767
- * @since 3.0.0
768
- */
769
- off(event: HookEvent, callback: HookCallback): boolean {
770
- return this.hookManager.off(event, callback);
771
- }
772
-
773
- /**
774
- * Añade un middleware al pipeline
775
- *
776
- * @param middleware - Función middleware
777
- * @param priority - Prioridad (mayor = primero)
778
- * @returns Función para desregistrar
779
- *
780
- * @example
781
- * logger.use((entry, next) => {
782
- * entry.requestId = asyncLocalStorage.getStore()?.requestId;
783
- * next();
784
- * });
785
- *
786
- * @since 3.0.0
787
- */
788
- use(middleware: MiddlewareFn, priority?: number): () => void {
789
- return this.hookManager.use(middleware, priority);
790
- }
791
-
792
- /**
793
- * Obtiene el HookManager
794
- *
795
- * @returns HookManager
796
- * @since 3.0.0
797
- */
798
- getHookManager(): HookManager {
799
- return this.hookManager;
800
- }
801
-
802
- // ===== TRANSPORTS =====
803
-
804
- /**
805
- * Añade un transport para envío de logs
806
- *
807
- * @param target - Configuración del transport
808
- * @returns ID único del transport
809
- *
810
- * @example
811
- * // File transport
812
- * logger.addTransport({
813
- * target: 'file',
814
- * options: { destination: '/var/log/app.log' }
815
- * });
816
- *
817
- * @example
818
- * // HTTP transport con batching
819
- * logger.addTransport({
820
- * target: 'http',
821
- * options: {
822
- * url: 'https://logs.example.com',
823
- * batchSize: 100,
824
- * flushInterval: 5000
825
- * },
826
- * level: 'warn'
827
- * });
828
- *
829
- * @since 3.0.0
830
- */
831
- addTransport(target: TransportTarget): string {
832
- if (!this.transportManager) {
833
- this.transportManager = new TransportManager();
834
- }
835
- return this.transportManager.add(target);
836
- }
837
-
838
- /**
839
- * Elimina un transport
840
- *
841
- * @param id - ID del transport a remover
842
- * @returns true si se eliminó
843
- *
844
- * @since 3.0.0
845
- */
846
- removeTransport(id: string): boolean {
847
- return this.transportManager?.remove(id) ?? false;
848
- }
849
-
850
- /**
851
- * Fuerza el flush de todos los transports
852
- *
853
- * @returns Promise que resuelve cuando todos los buffers están vaciados
854
- *
855
- * @since 3.0.0
856
- */
857
- async flushTransports(): Promise<void> {
858
- await this.transportManager?.flush();
859
- }
860
-
861
- /**
862
- * Cierra todos los transports
863
- *
864
- * @returns Promise que resuelve cuando todos están cerrados
865
- *
866
- * @since 3.0.0
867
- */
868
- async closeTransports(): Promise<void> {
869
- await this.transportManager?.close();
870
- }
871
-
872
- /**
873
- * Obtiene el TransportManager
874
- *
875
- * @returns TransportManager o undefined si no hay transports
876
- * @since 3.0.0
877
- */
878
- getTransportManager(): TransportManager | undefined {
879
- return this.transportManager;
880
- }
881
-
882
- // ===== CORE LOGGING METHODS =====
883
-
884
- /**
885
- * Verifica si un nivel de log debe mostrarse según la verbosidad actual
886
- * @private
887
- * @param {LogLevel} level - Nivel de log a verificar
888
- * @returns {boolean} True si debe mostrarse, false si no
889
- */
890
- private shouldLog(level: LogLevel): boolean {
891
- if (this.config.verbosity === 'silent') return false;
892
- const levels = { debug: 0, info: 1, warn: 2, error: 3, critical: 4 };
893
- return levels[level] >= levels[this.config.verbosity];
894
- }
895
-
896
- /**
897
- * Obtiene el prefijo efectivo (global + scope)
898
- * @private
899
- * @returns {string | undefined} Prefijo combinado o undefined
900
- */
901
- private getEffectivePrefix(): string | undefined {
902
- const parts = [this.config.globalPrefix, this.scopedPrefix].filter(Boolean);
903
- return parts.length > 0 ? parts.join(':') : undefined;
904
- }
905
-
906
- /**
907
- * Método central de logging que maneja estilos y formato
908
- * @protected
909
- * @param {LogLevel} level - Nivel del log
910
- * @param {...any} args - Argumentos a loggear
911
- */
912
- protected log(level: LogLevel, ...args: any[]): void {
913
- if (!this.shouldLog(level)) return;
914
-
915
- const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
916
- const prefix = this.getEffectivePrefix();
917
- const timestamp = formatTimestamp();
918
-
919
- // Serialize args using registry
920
- const serializedArgs = args.map(arg => this.serializerRegistry.serialize(arg));
921
-
922
- // Prepend badges to message if any
923
- let message = serializedArgs.length > 0 ? String(serializedArgs[0]) : '';
924
- if (this.badgeList.length > 0 && this.displaySettings.showBadges) {
925
- const badgePrefix = this.badgeList.map(b => `[${b}]`).join('');
926
- message = badgePrefix + ' ' + message;
927
- }
928
- const additionalArgs = serializedArgs.slice(1);
929
-
930
- // Process beforeLog hooks (sync for performance)
931
- let hookEntry = {
932
- level,
933
- message,
934
- args: serializedArgs,
935
- timestamp,
936
- prefix,
937
- stackInfo: stackInfo || undefined
938
- };
939
-
940
- // Emit beforeLog event (fire-and-forget for sync logging)
941
- this.hookManager.emit('beforeLog', hookEntry).then(processed => {
942
- message = processed.message;
943
- }).catch(() => {});
944
-
945
- // Create styled output with theme detection and display settings
946
- const [format, ...styles] = createStyledOutput(
947
- level,
948
- LEVEL_STYLES,
949
- prefix,
950
- message,
951
- this.displaySettings.showLocation ? stackInfo : null,
952
- this.config.autoDetectTheme,
953
- (this as any)._activePreset,
954
- (this as any)._activePresetName
955
- );
956
-
957
- // Add group indentation
958
- const groupIndent = ' '.repeat(this.groupDepth);
959
- const finalFormat = groupIndent + format;
960
-
961
- // Output via configured writer (console by default)
962
- this.writeOutput(finalFormat, level, styles, additionalArgs);
963
-
964
- // Update export handler group info
965
- if (this.exportHandler) {
966
- this.exportHandler.setGroupInfo(this.groupDepth);
967
- }
968
-
969
- // Call custom handlers
970
- const metadata: LogMetadata = {
971
- timestamp,
972
- level,
973
- prefix,
974
- stackInfo: stackInfo ? stackInfo : undefined,
975
- };
976
-
977
- this.handlers.forEach(handler => {
978
- try {
979
- handler.handle(level, message, serializedArgs, metadata);
980
- } catch (error) {
981
- console.error('Log handler failed:', error);
982
- }
983
- });
984
-
985
- // Write to transports (async, fire-and-forget)
986
- if (this.transportManager) {
987
- const levelValues: Record<LogLevel, number> = {
988
- debug: 0, info: 1, warn: 2, error: 3, critical: 4
989
- };
990
- const record: TransportRecord = {
991
- level,
992
- levelValue: levelValues[level],
993
- time: Date.now(),
994
- msg: message,
995
- prefix,
996
- location: stackInfo ? {
997
- file: stackInfo.file,
998
- line: stackInfo.line,
999
- column: stackInfo.column,
1000
- function: stackInfo.function
1001
- } : undefined
1002
- };
1003
- this.transportManager.write(record).catch(() => {});
1004
- }
1005
-
1006
- // Emit afterLog event (fire-and-forget)
1007
- this.hookManager.emit('afterLog', hookEntry).catch(() => {});
1008
- }
1009
-
1010
- logWithBindings(bindings: Bindings, level: LogLevel, ...args: any[]): void {
1011
- if (!this.shouldLog(level)) return;
1012
-
1013
- let prefix = '';
1014
- const colorCapability = getColorCapability();
1015
-
1016
- if (bindings.badges?.length) {
1017
- prefix += bindings.badges.map(b => formatBadge(b, 'pill', colorCapability, '#00ff88')).join(' ') + ' ';
1018
- }
1019
- if (bindings.scope) {
1020
- prefix += formatBadge(bindings.scope, 'pill', colorCapability, '#00ffff') + ' ';
1021
- }
1022
-
1023
- if (prefix && args.length > 0) {
1024
- args[0] = prefix + String(args[0]);
1025
- }
1026
-
1027
- this.log(level, ...args);
1028
- }
1029
-
1030
- debug(...args: any[]): void {
1031
- this.log('debug', ...args);
1032
- }
1033
-
1034
- /**
1035
- * Registra mensajes informativos
1036
- *
1037
- * @param {...any} args - Mensajes y datos informativos
1038
- *
1039
- * @example
1040
- * logger.info('Servidor iniciado en puerto 3000');
1041
- * logger.info('Usuario conectado:', userId);
1042
- * logger.info('Procesando', totalItems, 'elementos');
1043
- *
1044
- * @since 0.3.0
1045
- */
1046
- info(...args: any[]): void {
1047
- this.log('info', ...args);
1048
- }
1049
-
1050
- /**
1051
- * Registra mensajes de advertencia
1052
- *
1053
- * @param {...any} args - Mensajes de advertencia
1054
- *
1055
- * @example
1056
- * logger.warn('Memoria al 85% de capacidad');
1057
- * logger.warn('API deprecada, usar v2');
1058
- * logger.warn('Reintentos agotados:', maxRetries);
1059
- *
1060
- * @since 0.3.0
1061
- */
1062
- warn(...args: any[]): void {
1063
- this.log('warn', ...args);
1064
- }
1065
-
1066
- /**
1067
- * Registra mensajes de error
1068
- *
1069
- * @param {...any} args - Mensajes de error y stack traces
1070
- *
1071
- * @example
1072
- * logger.error('Fallo en conexión a base de datos');
1073
- * logger.error('Error al procesar:', error.message, error.stack);
1074
- * logger.error('Código de error:', errorCode);
1075
- *
1076
- * @since 0.3.0
1077
- */
1078
- error(...args: any[]): void {
1079
- this.log('error', ...args);
1080
- }
1081
-
1082
- /**
1083
- * Registra mensajes de éxito (nivel info especial)
1084
- *
1085
- * @param {...any} args - Mensajes de operaciones exitosas
1086
- *
1087
- * @example
1088
- * logger.success('Base de datos conectada');
1089
- * logger.success('Usuario creado con ID:', userId);
1090
- * logger.success('✓ Tests pasados: 42/42');
1091
- *
1092
- * @since 0.3.0
1093
- */
1094
- success(...args: any[]): void {
1095
- if (!this.shouldLog('info')) return;
1096
-
1097
- const stackInfo = this.config.enableStackTrace ? parseStackTrace() : null;
1098
- const prefix = this.getEffectivePrefix();
1099
- const message = args.length > 0 ? String(args[0]) : '';
1100
- const additionalArgs = args.slice(1);
1101
-
1102
- // Handle success as special case - use info level with success styling
1103
- const [format, ...styles] = createStyledOutput(
1104
- 'info',
1105
- LEVEL_STYLES,
1106
- prefix,
1107
- message,
1108
- this.displaySettings.showLocation ? stackInfo : null,
1109
- this.config.autoDetectTheme,
1110
- (this as any)._activePreset,
1111
- (this as any)._activePresetName
1112
- );
1113
-
1114
- // Override with success styling
1115
- const successStyle = LEVEL_STYLES.success;
1116
- let emoji = '✅';
1117
- let label = 'SUCCESS';
1118
-
1119
- if (successStyle) {
1120
- if (successStyle.emoji) {
1121
- emoji = successStyle.emoji;
1122
- }
1123
- if (successStyle.label) {
1124
- label = successStyle.label;
1125
- }
1126
- }
1127
-
1128
- const successFormat = format.replace(/ℹ️ INFO/, `${emoji} ${label}`);
1129
-
1130
- const groupIndent = ' '.repeat(this.groupDepth);
1131
- const finalFormat = groupIndent + successFormat;
1132
-
1133
- if (additionalArgs.length > 0) {
1134
- console.log(finalFormat, ...styles, ...additionalArgs);
1135
- } else {
1136
- console.log(finalFormat, ...styles);
1137
- }
1138
-
1139
- // Call handlers
1140
- const metadata: LogMetadata = {
1141
- timestamp: formatTimestamp(),
1142
- level: 'info',
1143
- prefix,
1144
- stackInfo: stackInfo ? stackInfo : undefined,
1145
- };
1146
-
1147
- this.handlers.forEach(handler => {
1148
- try {
1149
- handler.handle('info', message, args, metadata);
1150
- } catch (error) {
1151
- console.error('Log handler failed:', error);
1152
- }
1153
- });
1154
- }
1155
-
1156
- /**
1157
- * Registra información de trace (debugging detallado)
1158
- *
1159
- * @param {...any} args - Datos detallados para debugging
1160
- *
1161
- * @example
1162
- * logger.trace('Entrando en función processData');
1163
- * logger.trace('Stack completo:', new Error().stack);
1164
- *
1165
- * @since 0.3.0
1166
- */
1167
- trace(...args: any[]): void {
1168
- this.log('debug', ...args);
1169
- if (this.shouldLog('debug')) {
1170
- console.trace(...args);
1171
- }
1172
- }
1173
-
1174
- /**
1175
- * Registra errores críticos (prioridad más alta)
1176
- *
1177
- * @param {...any} args - Errores críticos del sistema
1178
- *
1179
- * @example
1180
- * logger.critical('Sistema caído - reinicio inmediato requerido');
1181
- * logger.critical('Pérdida de datos detectada');
1182
- * logger.critical('Brecha de seguridad:', securityError);
1183
- *
1184
- * @since 0.3.0
1185
- */
1186
- critical(...args: any[]): void {
1187
- this.log('critical', ...args);
1188
- }
1189
-
1190
- // ===== ADVANCED LOGGING FEATURES =====
1191
-
1192
- /**
1193
- * Muestra datos en formato de tabla
1194
- *
1195
- * @param {any} data - Datos a mostrar (array de objetos o matriz)
1196
- * @param {string[]} columns - Columnas específicas a mostrar (opcional)
1197
- *
1198
- * @example
1199
- * const usuarios = [
1200
- * { id: 1, nombre: 'Juan', edad: 30 },
1201
- * { id: 2, nombre: 'María', edad: 25 }
1202
- * ];
1203
- * logger.table(usuarios);
1204
- * logger.table(usuarios, ['nombre', 'edad']); // Solo estas columnas
1205
- *
1206
- * @since 0.3.0
1207
- */
1208
- table(data: any, columns?: string[]): void {
1209
- if (!this.shouldLog('info')) return;
1210
-
1211
- const prefix = this.getEffectivePrefix();
1212
- const tableStyle = StylePresets.accent().build();
1213
-
1214
- const format = `%c📊 TABLE${prefix ? ` [${prefix}]` : ''}`;
1215
- console.log(format, tableStyle);
1216
-
1217
- if (columns) {
1218
- console.table(data, columns);
1219
- } else {
1220
- console.table(data);
1221
- }
1222
- }
1223
-
1224
- /**
1225
- * Inicia un grupo colapsable en la consola
1226
- *
1227
- * @param {string} label - Etiqueta del grupo
1228
- * @param {boolean} collapsed - Si el grupo inicia colapsado (default: false)
1229
- *
1230
- * @example
1231
- * logger.group('Procesando usuarios');
1232
- * logger.info('Usuario 1 procesado');
1233
- * logger.info('Usuario 2 procesado');
1234
- * logger.groupEnd();
1235
- *
1236
- * @example
1237
- * // Grupo colapsado por defecto
1238
- * logger.group('Detalles adicionales', true);
1239
- * logger.debug('Información detallada aquí');
1240
- * logger.groupEnd();
1241
- *
1242
- * @since 0.3.0
1243
- */
1244
- group(label: string, collapsed: boolean = false): void {
1245
- const groupStyle = new StyleBuilder()
1246
- .bg('linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%)')
1247
- .color('#1565c0')
1248
- .border('1px solid #90caf9')
1249
- .padding('4px 12px')
1250
- .rounded('6px')
1251
- .bold()
1252
- .build();
1253
-
1254
- const format = `%c📁 ${label}`;
1255
-
1256
- if (collapsed) {
1257
- console.groupCollapsed(format, groupStyle);
1258
- } else {
1259
- console.group(format, groupStyle);
1260
- }
1261
-
1262
- this.groupDepth++;
1263
- }
1264
-
1265
- /**
1266
- * Finaliza el grupo actual de la consola
1267
- *
1268
- * @example
1269
- * logger.group('Operaciones');
1270
- * logger.info('Operación 1');
1271
- * logger.info('Operación 2');
1272
- * logger.groupEnd(); // Cierra el grupo
1273
- *
1274
- * @since 0.3.0
1275
- */
1276
- groupEnd(): void {
1277
- if (this.groupDepth > 0) {
1278
- console.groupEnd();
1279
- this.groupDepth--;
1280
- }
1281
- }
1282
-
1283
- // ===== PERFORMANCE TIMING =====
1284
-
1285
- /**
1286
- * Inicia un temporizador con la etiqueta dada
1287
- *
1288
- * @param {string} label - Etiqueta identificadora del temporizador
1289
- *
1290
- * @example
1291
- * logger.time('proceso-datos');
1292
- * // ... operación costosa ...
1293
- * logger.timeEnd('proceso-datos'); // ⏱️ Timer ended: proceso-datos - 1523.45ms
1294
- *
1295
- * @since 0.3.0
1296
- */
1297
- time(label: string): void {
1298
- const timer: TimerEntry = {
1299
- label,
1300
- startTime: performance.now(),
1301
- };
1302
- this.timers.set(label, timer);
1303
-
1304
- const timerStyle = StylePresets.warning().build();
1305
- console.log(`%c⏱️ Timer started: ${label}`, timerStyle);
1306
- }
1307
-
1308
- /**
1309
- * Finaliza un temporizador y muestra el tiempo transcurrido
1310
- *
1311
- * @param {string} label - Etiqueta del temporizador a finalizar
1312
- * @returns {number} Elapsed milliseconds, or -1 if timer not found
1313
- *
1314
- * @example
1315
- * logger.time('consulta-db');
1316
- * await consultarBaseDatos();
1317
- * const elapsed = logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
1318
- *
1319
- * @since 0.3.0
1320
- */
1321
- timeEnd(label: string): number {
1322
- const timer = this.timers.get(label);
1323
- if (!timer) {
1324
- this.warn(`Timer '${label}' does not exist`);
1325
- return -1;
1326
- }
1327
-
1328
- const elapsed = performance.now() - timer.startTime;
1329
- this.timers.delete(label);
1330
-
1331
- const timerStyle = StylePresets.success().build();
1332
- console.log(`%c⏱️ Timer ended: ${label} - ${elapsed.toFixed(2)}ms`, timerStyle);
1333
-
1334
- return elapsed;
1335
- }
1336
-
1337
- // ===== ADVANCED VISUAL FEATURES =====
1338
-
1339
- /**
1340
- * Muestra un banner con el tipo especificado o configurado
1341
- *
1342
- * @param {BannerType} bannerType - Tipo de banner (opcional)
1343
- *
1344
- * @example
1345
- * logger.showBanner('ascii'); // Banner ASCII art
1346
- * logger.showBanner('unicode'); // Banner con caracteres Unicode
1347
- * logger.showBanner('svg'); // Banner con gráfico SVG
1348
- * logger.showBanner(); // Usa el tipo configurado
1349
- *
1350
- * @since 0.3.0
1351
- */
1352
- showBanner(bannerType?: BannerType): void {
1353
- const effectiveBannerType = bannerType ? bannerType : this.config.bannerType;
1354
- displayInitBanner(effectiveBannerType);
1355
- }
1356
-
1357
- /**
1358
- * Registra mensaje con imagen SVG de fondo
1359
- *
1360
- * @param {string} message - Mensaje a mostrar
1361
- * @param {string} svgContent - Contenido SVG personalizado (opcional)
1362
- * @param {StyleOptions} options - Opciones de estilo (ancho, alto, padding)
1363
- *
1364
- * @example
1365
- * // SVG automático con gradiente
1366
- * logger.logWithSVG('🎆 Bienvenido a Better Logger');
1367
- *
1368
- * @example
1369
- * // SVG personalizado
1370
- * const customSVG = '<svg>...</svg>';
1371
- * logger.logWithSVG('Logo', customSVG, { width: 400, height: 100 });
1372
- *
1373
- * @since 0.3.0
1374
- */
1375
- logWithSVG(message: string, svgContent?: string, options: StyleOptions = {}): void {
1376
- const { width = 300, height = 60, padding = '30px 150px' } = options;
1377
-
1378
- let svgDataUri = '';
1379
- if (svgContent) {
1380
- const encodedSVG = encodeURIComponent(svgContent);
1381
- svgDataUri = `data:image/svg+xml,${encodedSVG}`;
1382
- } else {
1383
- 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>`;
1384
- svgDataUri = `data:image/svg+xml,${encodeURIComponent(defaultSVG)}`;
1385
- }
1386
-
1387
- const svgStyle = new StyleBuilder()
1388
- .bg(`url("${svgDataUri}") no-repeat center center`)
1389
- .padding(padding)
1390
- .color('transparent')
1391
- .rounded('4px')
1392
- .build();
1393
-
1394
- console.log(`%c${message}`, svgStyle);
1395
- }
1396
-
1397
- /**
1398
- * Registra mensaje con gradiente animado de fondo
1399
- *
1400
- * @param {string} message - Mensaje a animar
1401
- * @param {number} duration - Duración de la animación en segundos (default: 3)
1402
- *
1403
- * @example
1404
- * logger.logAnimated('🌈 Animación en progreso');
1405
- * logger.logAnimated('Cargando...', 5); // Animación de 5 segundos
1406
- *
1407
- * @since 0.3.0
1408
- */
1409
- logAnimated(message: string, duration: number = 3): void {
1410
- // Inject CSS animation if not already present
1411
- if (!document.getElementById('logger-animations')) {
1412
- const style = document.createElement('style');
1413
- style.id = 'logger-animations';
1414
- style.textContent = `
1415
- @keyframes loggerGradient {
1416
- 0% { background-position: 0% 50%; }
1417
- 50% { background-position: 100% 50%; }
1418
- 100% { background-position: 0% 50%; }
1419
- }
1420
- `;
1421
- document.head.appendChild(style);
1422
- }
1423
-
1424
- const animatedStyle = new StyleBuilder()
1425
- .bg('linear-gradient(-45deg, #667eea, #764ba2, #667eea, #764ba2)')
1426
- .css('background-size', '400% 400%')
1427
- .color('#ffffff')
1428
- .padding('12px 20px')
1429
- .rounded('8px')
1430
- .bold()
1431
- .font('Monaco, Consolas, monospace')
1432
- .animation(`loggerGradient ${duration}s ease infinite`)
1433
- .display('inline-block')
1434
- .build();
1435
-
1436
- console.log(`%c${message}`, animatedStyle);
1437
- }
1438
-
1439
- /**
1440
- * Agrupa logs por una propiedad específica usando Object.groupBy (cuando esté disponible)
1441
- *
1442
- * @param {T[]} items - Array de elementos a agrupar
1443
- * @param {Function} groupBy - Función que retorna la clave de agrupación
1444
- *
1445
- * @example
1446
- * const ventas = [
1447
- * { producto: 'Laptop', categoria: 'Electrónica', precio: 1200 },
1448
- * { producto: 'Mouse', categoria: 'Electrónica', precio: 25 },
1449
- * { producto: 'Libro', categoria: 'Literatura', precio: 15 }
1450
- * ];
1451
- * logger.logGrouped(ventas, item => item.categoria);
1452
- *
1453
- * @since 0.3.0
1454
- */
1455
- logGrouped<T>(items: T[], groupBy: (item: T) => string): void {
1456
- try {
1457
- // Use Object.groupBy if available (ES2024), otherwise fallback to reduce
1458
- let grouped: Record<string, T[]>;
1459
-
1460
- if ((Object as any).groupBy) {
1461
- grouped = (Object as any).groupBy(items, groupBy);
1462
- } else {
1463
- grouped = items.reduce((acc, item) => {
1464
- const key = groupBy(item);
1465
- if (!acc[key]) {
1466
- acc[key] = [];
1467
- }
1468
- acc[key].push(item);
1469
- return acc;
1470
- }, {} as Record<string, T[]>);
1471
- }
1472
-
1473
- Object.entries(grouped).forEach(([group, groupItems]) => {
1474
- this.group(`Group: ${group}`);
1475
- this.table(groupItems);
1476
- this.groupEnd();
1477
- });
1478
- } catch {
1479
- this.info('Grouped data:', items);
1480
- }
1481
- }
1482
-
1483
- // ===== CLI PRIMITIVES (v5.0) =====
1484
-
1485
- /**
1486
- * Displays a step progress indicator in the terminal
1487
- *
1488
- * @param {number} current - Current step number
1489
- * @param {number} total - Total number of steps
1490
- * @param {string} message - Step description
1491
- *
1492
- * @example
1493
- * logger.step(1, 5, 'Analyzing repository...');
1494
- * logger.step(2, 5, 'Generating commit message...');
1495
- *
1496
- * @since 5.0.0
1497
- */
1498
- step(current: number, total: number, message: string): void {
1499
- if (!this._showPrimitives) return;
1500
- if (!isRunningInTerminal()) {
1501
- this.getServerFallback().step(current, total, message);
1502
- return;
1503
- }
1504
- const colorCap = getColorCapability();
1505
- const output = renderStep(current, total, message, colorCap);
1506
- process.stderr.write(output + '\n');
1507
- }
1508
-
1509
- /**
1510
- * Displays a styled header with optional subtitle
1511
- *
1512
- * @param {string} title - Main title text
1513
- * @param {string} subtitle - Optional subtitle (rendered dimmed)
1514
- *
1515
- * @example
1516
- * logger.header('Commit Wizard', 'v2.0.0');
1517
- *
1518
- * @since 5.0.0
1519
- */
1520
- header(title: string, subtitle?: string): void {
1521
- if (!this._showPrimitives) return;
1522
- if (!isRunningInTerminal()) {
1523
- this.getServerFallback().header(title, subtitle);
1524
- return;
1525
- }
1526
- const output = renderHeader(title, subtitle);
1527
- process.stderr.write(output + '\n');
1528
- }
1529
-
1530
- /**
1531
- * Displays a horizontal divider line
1532
- *
1533
- * @example
1534
- * logger.divider();
1535
- *
1536
- * @since 5.0.0
1537
- */
1538
- divider(): void {
1539
- if (!this._showPrimitives) return;
1540
- if (!isRunningInTerminal()) {
1541
- this.getServerFallback().divider();
1542
- return;
1543
- }
1544
- const output = renderDivider();
1545
- process.stderr.write(output + '\n');
1546
- }
1547
-
1548
- /**
1549
- * Outputs a blank line
1550
- *
1551
- * @example
1552
- * logger.blank();
1553
- *
1554
- * @since 5.0.0
1555
- */
1556
- blank(): void {
1557
- if (!this._showPrimitives) return;
1558
- if (!isRunningInTerminal()) {
1559
- this.getServerFallback().blank();
1560
- return;
1561
- }
1562
- process.stderr.write('\n');
1563
- }
1564
-
1565
- /**
1566
- * Renders content inside a bordered box
1567
- *
1568
- * @param {string} content - Content string (may contain newlines)
1569
- * @param {IBoxOptions} options - Box rendering options
1570
- *
1571
- * @example
1572
- * logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
1573
- *
1574
- * @since 5.0.0
1575
- */
1576
- box(content: string, options?: IBoxOptions): void {
1577
- if (!this._showPrimitives) return;
1578
- if (!isRunningInTerminal()) {
1579
- this.getServerFallback().box(content, options);
1580
- return;
1581
- }
1582
- const colorCap = getColorCapability();
1583
- const output = renderBox(content, options, colorCap);
1584
- process.stderr.write(output + '\n');
1585
- }
1586
-
1587
- /**
1588
- * Renders an array of objects as a formatted ASCII table.
1589
- * Note: This is distinct from the existing table() method which uses console.table.
1590
- *
1591
- * @param {Record<string, unknown>[]} rows - Array of row objects
1592
- * @param {ITableOptions} options - Table rendering options
1593
- *
1594
- * @example
1595
- * logger.cliTable([
1596
- * { provider: 'Groq', status: 'Available', model: 'llama-3.3-70b' },
1597
- * { provider: 'Gemini', status: 'Configured', model: 'gemini-2.5-flash' },
1598
- * ]);
1599
- *
1600
- * @since 5.0.0
1601
- */
1602
- cliTable(rows: Record<string, unknown>[], options?: ITableOptions): void {
1603
- if (!this._showPrimitives) return;
1604
- if (!isRunningInTerminal()) {
1605
- this.getServerFallback().cliTable(rows, options);
1606
- return;
1607
- }
1608
- const colorCap = getColorCapability();
1609
- const output = renderTable(rows, options, colorCap);
1610
- process.stderr.write(output + '\n');
1611
- }
1612
-
1613
- /**
1614
- * Creates a spinner handle for showing progress during async operations.
1615
- * Returns a NoopSpinner in non-TTY environments.
1616
- *
1617
- * @param {string} message - Initial spinner text
1618
- * @returns {ISpinnerHandle} Spinner controller
1619
- *
1620
- * @example
1621
- * const s = logger.spinner('Analyzing repository...');
1622
- * s.start();
1623
- * await analyzeRepo();
1624
- * s.succeed('Analysis complete (1.2s)');
1625
- *
1626
- * @since 5.0.0
1627
- */
1628
- spinner(message: string): ISpinnerHandle {
1629
- if (!isRunningInTerminal() || this.config.outputMode === 'silent') {
1630
- return new NoopSpinner(message, this);
1631
- }
1632
- return new SpinnerManager(message, this.config, this);
1633
- }
1634
-
1635
- /**
1636
- * Sets the CLI verbosity level, controlling both log verbosity and primitive visibility
1637
- *
1638
- * @param {CLILogLevel} level - CLI log level
1639
- *
1640
- * @example
1641
- * logger.setCLILevel('quiet'); // Only errors, no CLI primitives
1642
- * logger.setCLILevel('verbose'); // Debug logs + all CLI primitives
1643
- *
1644
- * @since 5.0.0
1645
- */
1646
- setCLILevel(level: CLILogLevel): void {
1647
- const mapping = CLI_LEVEL_MAP[level];
1648
- this.setVerbosity(mapping.verbosity);
1649
- this._showPrimitives = mapping.showPrimitives;
1650
- this.config.cliLevel = level;
1651
- }
1652
-
1653
- /**
1654
- * Returns the current CLI log level
1655
- * @returns {CLILogLevel} Current CLI log level
1656
- * @since 5.0.0
1657
- */
1658
- get cliLevel(): CLILogLevel {
1659
- return this.config.cliLevel ?? 'normal';
1660
- }
1661
-
1662
- /** Lazily creates the server fallback instance @private */
1663
- private getServerFallback(): ServerFallback {
1664
- if (!this._serverFallback) {
1665
- this._serverFallback = new ServerFallback(this);
1666
- }
1667
- return this._serverFallback;
1668
- }
1669
-
1670
- // ===== OUTPUT WRITER SYSTEM =====
1671
-
1672
- /**
1673
- * Writes formatted output to the configured destination.
1674
- * Respects outputMode configuration for console, silent, or custom output.
1675
- *
1676
- * @private
1677
- * @param {string} message - Formatted log message
1678
- * @param {LogLevel} level - Log level
1679
- * @param {string[]} styles - CSS styles for browser console
1680
- * @param {any[]} additionalArgs - Additional arguments to log
1681
- * @since 4.0.0
1682
- */
1683
- private writeOutput(
1684
- message: string,
1685
- level: LogLevel,
1686
- styles: string[],
1687
- additionalArgs: any[]
1688
- ): void {
1689
- const mode = this.config.outputMode ?? 'console';
1690
-
1691
- // Silent mode: no output
1692
- if (mode === 'silent') {
1693
- return;
1694
- }
1695
-
1696
- // Custom mode: use configured writer
1697
- if (mode === 'custom' && this.config.outputWriter) {
1698
- const fullMessage = additionalArgs.length > 0
1699
- ? `${message} ${additionalArgs.map(a => String(a)).join(' ')}`
1700
- : message;
1701
- this.config.outputWriter.write(fullMessage, level, styles);
1702
- return;
1703
- }
1704
-
1705
- // Default: console output
1706
- if (additionalArgs.length > 0) {
1707
- console.log(message, ...styles, ...additionalArgs);
1708
- } else {
1709
- console.log(message, ...styles);
1710
- }
1711
- }
1712
-
1713
- // ===== CLI SYSTEM =====
1714
-
1715
- /**
1716
- * Procesador de comandos CLI para configuración y exportación del logger
1717
- *
1718
- * @param {string} command - Comando CLI a ejecutar
1719
- * @returns {Promise<void>}
1720
- *
1721
- * @example
1722
- * // Comandos disponibles
1723
- * await logger.cli('export json'); // Exporta logs en JSON
1724
- * await logger.cli('export csv'); // Exporta logs en CSV
1725
- * await logger.cli('theme list'); // Lista temas disponibles
1726
- * await logger.cli('theme set neon'); // Cambia al tema neon
1727
- * await logger.cli('config show'); // Muestra configuración actual
1728
- * await logger.cli('history clear'); // Limpia historial de logs
1729
- * await logger.cli('status'); // Muestra estado del logger
1730
- * await logger.cli('help'); // Muestra ayuda de comandos
1731
- *
1732
- * @since 0.3.0
1733
- */
1734
- async cli(command: string): Promise<void> {
1735
- if (!this.cliProcessor) {
1736
- this.error('CLI processor not initialized');
1737
- return;
1738
- }
1739
-
1740
- await this.cliProcessor.processCommand(command, this);
1741
- }
1742
- }
1743
-
1744
- /**
1745
- * Lazy singleton instance - se inicializa solo cuando se necesita
1746
- * @private
1747
- */
1748
- let _defaultLogger: Logger | null = null;
1749
-
1750
- /**
1751
- * Obtiene o crea la instancia singleton del logger
1752
- * @returns {Logger} Instancia singleton del logger
1753
- */
1754
- function getDefaultLogger(): Logger {
1755
- if (!_defaultLogger) {
1756
- _defaultLogger = new Logger({
1757
- verbosity: 'info',
1758
- enableColors: true,
1759
- enableTimestamps: true,
1760
- enableStackTrace: true,
1761
- bufferSize: 1000, // Enable export functionality by default
1762
- });
1763
-
1764
- // Display initialization banner only once
1765
- try {
1766
- displayInitBanner();
1767
- } catch (error) {
1768
- // Silent fail if banner cannot be displayed
1769
- }
1770
- }
1771
- return _defaultLogger;
1772
- }
1773
-
1774
- // Export the lazy singleton getter as default
1775
- export default getDefaultLogger();
1776
-
1777
- /**
1778
- * Métodos individuales exportados para conveniencia
1779
- * @description Todos los métodos están correctamente enlazados al singleton lazy
1780
- * @since 0.3.0
1781
- */
1782
- export const debug = (...args: any[]) => getDefaultLogger().debug(...args);
1783
- export const info = (...args: any[]) => getDefaultLogger().info(...args);
1784
- export const warn = (...args: any[]) => getDefaultLogger().warn(...args);
1785
- export const error = (...args: any[]) => getDefaultLogger().error(...args);
1786
- export const success = (...args: any[]) => getDefaultLogger().success(...args);
1787
- export const trace = (...args: any[]) => getDefaultLogger().trace(...args);
1788
- export const critical = (...args: any[]) => getDefaultLogger().critical(...args);
1789
- export const table = (data: any, columns?: string[]) => getDefaultLogger().table(data, columns);
1790
- export const group = (label: string, collapsed?: boolean) => getDefaultLogger().group(label, collapsed);
1791
- export const groupEnd = () => getDefaultLogger().groupEnd();
1792
- export const time = (label: string) => getDefaultLogger().time(label);
1793
- export const timeEnd = (label: string) => getDefaultLogger().timeEnd(label);
1794
- export const setGlobalPrefix = (prefix: string) => getDefaultLogger().setGlobalPrefix(prefix);
1795
- export const setVerbosity = (level: Verbosity) => getDefaultLogger().setVerbosity(level);
1796
- export const addHandler = (handler: ILogHandler) => getDefaultLogger().addHandler(handler);
1797
- export const setTheme = (theme: ThemeVariant) => getDefaultLogger().setTheme(theme);
1798
- export const setBannerType = (bannerType: BannerType) => getDefaultLogger().setBannerType(bannerType);
1799
- export const showBanner = (bannerType?: BannerType) => getDefaultLogger().showBanner(bannerType);
1800
- export const logWithSVG = (message: string, svgContent?: string, options?: StyleOptions) =>
1801
- getDefaultLogger().logWithSVG(message, svgContent, options);
1802
- export const logAnimated = (message: string, duration?: number) =>
1803
- getDefaultLogger().logAnimated(message, duration);
1804
- export const cli = (command: string) => getDefaultLogger().cli(command);
1805
- export const cleanup = () => getDefaultLogger().cleanup();
1806
-
1807
- // Simplified API exports
1808
- export const preset = (name: string) => getDefaultLogger().preset(name);
1809
- export const presets = () => getDefaultLogger().presets();
1810
- export const hideTimestamp = () => getDefaultLogger().hideTimestamp();
1811
- export const showTimestamp = () => getDefaultLogger().showTimestamp();
1812
- export const hideLocation = () => getDefaultLogger().hideLocation();
1813
- export const showLocation = () => getDefaultLogger().showLocation();
1814
- export const hideBadges = () => getDefaultLogger().hideBadges();
1815
- export const showBadges = () => getDefaultLogger().showBadges();
1816
- export const badges = (badgeList: string[]) => getDefaultLogger().badges(badgeList);
1817
- export const badge = (badgeName: string) => getDefaultLogger().badge(badgeName);
1818
- export const clearBadges = () => getDefaultLogger().clearBadges();
1819
- export const component = (name: string) => getDefaultLogger().component(name);
1820
- export const api = (name: string) => getDefaultLogger().api(name);
1821
- export const scope = (name: string) => getDefaultLogger().scope(name);
1822
- export const customize = (overrides: any) => getDefaultLogger().customize(overrides);
1823
- export const styles = () => getDefaultLogger().styles();
1824
-
1825
- // Enterprise features exports
1826
- export const addSerializer = <T>(
1827
- type: new (...args: any[]) => T,
1828
- serializer: SerializerFn<T>,
1829
- priority?: number
1830
- ) => getDefaultLogger().addSerializer(type, serializer, priority);
1831
- export const removeSerializer = <T>(type: new (...args: any[]) => T) =>
1832
- getDefaultLogger().removeSerializer(type);
1833
- export const on = (event: HookEvent, callback: HookCallback, priority?: number) =>
1834
- getDefaultLogger().on(event, callback, priority);
1835
- export const once = (event: HookEvent, callback: HookCallback, priority?: number) =>
1836
- getDefaultLogger().once(event, callback, priority);
1837
- export const off = (event: HookEvent, callback: HookCallback) =>
1838
- getDefaultLogger().off(event, callback);
1839
- export const use = (middleware: MiddlewareFn, priority?: number) =>
1840
- getDefaultLogger().use(middleware, priority);
1841
- export const addTransport = (target: TransportTarget) =>
1842
- getDefaultLogger().addTransport(target);
1843
- export const removeTransport = (id: string) =>
1844
- getDefaultLogger().removeTransport(id);
1845
- export const flushTransports = () =>
1846
- getDefaultLogger().flushTransports();
1847
- export const closeTransports = () =>
1848
- getDefaultLogger().closeTransports();
1849
-
1850
- // Re-export handlers and utilities for backward compatibility
1851
- export { FileLogHandler, RemoteLogHandler, AnalyticsLogHandler, ExportLogHandler } from './handlers/index.js';
1852
- export { StyleBuilder, StylePresets as Styles } from './styling/index.js';
1853
-
1854
- // Re-export enterprise features
1855
- export { SerializerRegistry } from './serializers/index.js';
1856
- export { HookManager } from './hooks/index.js';
1857
- export { TransportManager, ConsoleTransport, FileTransport, HttpTransport } from './transports/index.js';
1858
- export { StyleCache, getStyleCache } from './styling/StyleCache.js';