@mks2508/better-logger 0.18.2-alpha.1 → 0.18.3

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 (207) hide show
  1. package/README.md +38 -336
  2. package/dist/Logger.d.ts +356 -157
  3. package/dist/Logger.d.ts.map +1 -1
  4. package/dist/ScopedLogger.d.ts +549 -9
  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-L7HzynFw.cjs → LogContext-BaMXleWj.cjs} +19 -4
  11. package/dist/chunks/LogContext-BaMXleWj.cjs.map +1 -0
  12. package/dist/chunks/LogContext-DZasm_P5.cjs +141 -0
  13. package/dist/chunks/LogContext-DZasm_P5.cjs.map +1 -0
  14. package/dist/chunks/{LogContext-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
  15. package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
  16. package/dist/chunks/LogContext-Dyzs61XG.js +136 -0
  17. package/dist/chunks/LogContext-Dyzs61XG.js.map +1 -0
  18. package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
  19. package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
  20. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
  21. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
  22. package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
  23. package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
  24. package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
  25. package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
  26. package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
  27. package/dist/chunks/core-Blfi2klP.js.map +1 -0
  28. package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
  29. package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
  30. package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
  31. package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
  32. package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
  33. package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
  34. package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
  35. package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
  36. package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
  37. package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
  38. package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
  39. package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
  40. package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
  41. package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
  42. package/dist/chunks/styling-CRw3KQW4.js +1592 -0
  43. package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
  44. package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
  45. package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
  46. package/dist/chunks/transports-BGfwwakw.js +1237 -0
  47. package/dist/chunks/transports-BGfwwakw.js.map +1 -0
  48. package/dist/chunks/transports-BZ-Mc2IT.cjs +1450 -0
  49. package/dist/chunks/transports-BZ-Mc2IT.cjs.map +1 -0
  50. package/dist/chunks/transports-DvaLAeGJ.js +1403 -0
  51. package/dist/chunks/transports-DvaLAeGJ.js.map +1 -0
  52. package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
  53. package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
  54. package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
  55. package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
  56. package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
  57. package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
  58. package/dist/cli/CommandProcessor.d.ts +166 -19
  59. package/dist/cli/CommandProcessor.d.ts.map +1 -1
  60. package/dist/cli/commands/ConfigCommand.d.ts +36 -1
  61. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
  62. package/dist/cli/commands/ExportCommand.d.ts +49 -3
  63. package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
  64. package/dist/cli/commands/ThemeCommand.d.ts +62 -3
  65. package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
  66. package/dist/cli/help.d.ts +30 -2
  67. package/dist/cli/help.d.ts.map +1 -1
  68. package/dist/cli/index.d.ts +29 -2
  69. package/dist/cli/index.d.ts.map +1 -1
  70. package/dist/cli.cjs +2 -2
  71. package/dist/cli.js +2 -2
  72. package/dist/context/LogContext.d.ts +167 -70
  73. package/dist/context/LogContext.d.ts.map +1 -1
  74. package/dist/context.cjs +1 -1
  75. package/dist/context.js +1 -1
  76. package/dist/core.cjs +52 -29
  77. package/dist/core.cjs.map +1 -1
  78. package/dist/core.d.ts +50 -27
  79. package/dist/core.d.ts.map +1 -1
  80. package/dist/core.js +52 -29
  81. package/dist/core.js.map +1 -1
  82. package/dist/hooks/HookBridge.d.ts +15 -9
  83. package/dist/hooks/HookBridge.d.ts.map +1 -1
  84. package/dist/hooks/HookManager.d.ts +295 -2
  85. package/dist/hooks/HookManager.d.ts.map +1 -1
  86. package/dist/hooks.cjs +1 -1
  87. package/dist/hooks.js +1 -1
  88. package/dist/index.cjs +1415 -214
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.d.ts +5 -1
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1413 -215
  93. package/dist/index.js.map +1 -1
  94. package/dist/playground/TerminalBridge.d.ts +23 -16
  95. package/dist/playground/TerminalBridge.d.ts.map +1 -1
  96. package/dist/playground/box.d.ts +36 -5
  97. package/dist/playground/box.d.ts.map +1 -1
  98. package/dist/playground/cli-table.d.ts +41 -5
  99. package/dist/playground/cli-table.d.ts.map +1 -1
  100. package/dist/playground/divider.d.ts +22 -3
  101. package/dist/playground/divider.d.ts.map +1 -1
  102. package/dist/playground/header.d.ts +21 -4
  103. package/dist/playground/header.d.ts.map +1 -1
  104. package/dist/playground/server-fallback.d.ts +96 -9
  105. package/dist/playground/server-fallback.d.ts.map +1 -1
  106. package/dist/playground/spinner.d.ts +159 -10
  107. package/dist/playground/spinner.d.ts.map +1 -1
  108. package/dist/playground/step.d.ts +25 -6
  109. package/dist/playground/step.d.ts.map +1 -1
  110. package/dist/playground.cjs +1 -1
  111. package/dist/playground.js +1 -1
  112. package/dist/serializers/SerializerBridge.d.ts +13 -6
  113. package/dist/serializers/SerializerBridge.d.ts.map +1 -1
  114. package/dist/serializers/SerializerRegistry.d.ts +236 -0
  115. package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
  116. package/dist/serializers.cjs +1 -1
  117. package/dist/serializers.js +1 -1
  118. package/dist/styles/StyleManager.d.ts +138 -31
  119. package/dist/styles/StyleManager.d.ts.map +1 -1
  120. package/dist/styles.cjs +2 -2
  121. package/dist/styles.js +2 -2
  122. package/dist/styling/SmartPresets.d.ts +100 -6
  123. package/dist/styling/SmartPresets.d.ts.map +1 -1
  124. package/dist/styling/StyleBuilder.d.ts +453 -32
  125. package/dist/styling/StyleBuilder.d.ts.map +1 -1
  126. package/dist/styling/banners.d.ts +83 -7
  127. package/dist/styling/banners.d.ts.map +1 -1
  128. package/dist/styling/themes.d.ts +41 -2
  129. package/dist/styling/themes.d.ts.map +1 -1
  130. package/dist/transports/ConsoleTransport.d.ts +95 -0
  131. package/dist/transports/ConsoleTransport.d.ts.map +1 -1
  132. package/dist/transports/FileTransport.d.ts +99 -18
  133. package/dist/transports/FileTransport.d.ts.map +1 -1
  134. package/dist/transports/HttpTransport.d.ts +135 -22
  135. package/dist/transports/HttpTransport.d.ts.map +1 -1
  136. package/dist/transports/OtlpTraceTransport.d.ts +118 -0
  137. package/dist/transports/OtlpTraceTransport.d.ts.map +1 -0
  138. package/dist/transports/OtlpTransport.d.ts +80 -37
  139. package/dist/transports/OtlpTransport.d.ts.map +1 -1
  140. package/dist/transports/SpanRuntime.d.ts +73 -0
  141. package/dist/transports/SpanRuntime.d.ts.map +1 -0
  142. package/dist/transports/TransportBridge.d.ts +19 -13
  143. package/dist/transports/TransportBridge.d.ts.map +1 -1
  144. package/dist/transports/TransportManager.d.ts +232 -10
  145. package/dist/transports/TransportManager.d.ts.map +1 -1
  146. package/dist/transports/index.d.ts +1 -0
  147. package/dist/transports/index.d.ts.map +1 -1
  148. package/dist/transports-module.d.ts +3 -1
  149. package/dist/transports-module.d.ts.map +1 -1
  150. package/dist/transports.cjs +2 -1
  151. package/dist/transports.js +2 -2
  152. package/dist/types/core.d.ts +155 -59
  153. package/dist/types/core.d.ts.map +1 -1
  154. package/dist/types/hooks.d.ts +92 -14
  155. package/dist/types/hooks.d.ts.map +1 -1
  156. package/dist/types/index.d.ts +1 -1
  157. package/dist/types/index.d.ts.map +1 -1
  158. package/dist/types/serializers.d.ts +72 -0
  159. package/dist/types/serializers.d.ts.map +1 -1
  160. package/dist/types/transports.d.ts +163 -39
  161. package/dist/types/transports.d.ts.map +1 -1
  162. package/dist/utils/ansi-colors.d.ts +15 -15
  163. package/dist/utils/asyncLocalStorage.d.ts +33 -0
  164. package/dist/utils/asyncLocalStorage.d.ts.map +1 -0
  165. package/dist/utils/environment-detector.d.ts +11 -11
  166. package/dist/utils/formatting.d.ts +8 -8
  167. package/dist/utils/output.d.ts +9 -9
  168. package/dist/utils/output.d.ts.map +1 -1
  169. package/dist/utils/stackTrace.d.ts +2 -2
  170. package/package.json +24 -25
  171. package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
  172. package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
  173. package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
  174. package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
  175. package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
  176. package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
  177. package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
  178. package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
  179. package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
  180. package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
  181. package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
  182. package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
  183. package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
  184. package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
  185. package/dist/chunks/core-PoT7RrTK.js.map +0 -1
  186. package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
  187. package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
  188. package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
  189. package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
  190. package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
  191. package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
  192. package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
  193. package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
  194. package/dist/chunks/styling-84N8T97t.js +0 -941
  195. package/dist/chunks/styling-84N8T97t.js.map +0 -1
  196. package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
  197. package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
  198. package/dist/chunks/transports-BiDk345e.js +0 -715
  199. package/dist/chunks/transports-BiDk345e.js.map +0 -1
  200. package/dist/chunks/transports-COPWmlF1.cjs +0 -756
  201. package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
  202. package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
  203. package/dist/chunks/utils-VETbVpkR.js.map +0 -1
  204. package/dist/example.d.ts +0 -18
  205. package/dist/example.d.ts.map +0 -1
  206. package/dist/main.d.ts +0 -2
  207. package/dist/main.d.ts.map +0 -1
package/dist/index.cjs CHANGED
@@ -2,24 +2,64 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_core = require("./chunks/core-Dzz7agGa.cjs");
6
- const require_transports = require("./chunks/transports-COPWmlF1.cjs");
7
- const require_utils = require("./chunks/utils-BqlFYocD.cjs");
8
- const require_styling = require("./chunks/styling-Cg5saQ46.cjs");
9
- const require_environment_detector = require("./chunks/environment-detector-Cnn6wr6O.cjs");
10
- const require_spinner = require("./chunks/spinner-DNvxbM9a.cjs");
11
- const require_LogContext = require("./chunks/LogContext-L7HzynFw.cjs");
12
- const require_HookBridge = require("./chunks/HookBridge-CiRfR67f.cjs");
13
- const require_SerializerBridge = require("./chunks/SerializerBridge-BaOQOb8q.cjs");
14
- const require_server_fallback = require("./chunks/server-fallback-BUKjdLS7.cjs");
15
- const require_StyleManager = require("./chunks/StyleManager-CIpd6wbO.cjs");
5
+ const require_core = require("./chunks/core-CqS_UBzJ.cjs");
6
+ const require_transports = require("./chunks/transports-BZ-Mc2IT.cjs");
7
+ const require_utils = require("./chunks/utils-W_cxqriN.cjs");
8
+ const require_styling = require("./chunks/styling-Cel2wPRy.cjs");
9
+ const require_environment_detector = require("./chunks/environment-detector-D-tHkKWA.cjs");
10
+ const require_spinner = require("./chunks/spinner-BHyYEXsM.cjs");
11
+ const require_LogContext = require("./chunks/LogContext-DZasm_P5.cjs");
12
+ const require_HookBridge = require("./chunks/HookBridge-C-AvXmPD.cjs");
13
+ const require_SerializerBridge = require("./chunks/SerializerBridge-C4a9Z37F.cjs");
14
+ const require_server_fallback = require("./chunks/server-fallback-CaCPjWby.cjs");
15
+ const require_StyleManager = require("./chunks/StyleManager-DQ6UNRB-.cjs");
16
16
  //#region src/ScopedLogger.ts
17
+ /**
18
+ * Logger prefijado por un scope nominal. Mantiene su propio stack de badges
19
+ * y contextos y delega el envío de mensajes al {@link Logger} padre a través
20
+ * de bindings (`{ scope, badges }`).
21
+ *
22
+ * Es la base de la jerarquía temática: {@link APILogger} y
23
+ * {@link ComponentLogger} extienden de ella, y {@link ContextLogger} la
24
+ * consume para apilar/subdesapilar sub-prefijos en el scope.
25
+ *
26
+ * No se construye directamente: se obtiene con `logger.scope('name')`.
27
+ *
28
+ * @example
29
+ * // El factory method del Logger raíz devuelve un ScopedLogger
30
+ * import logger from '@mks2508/better-logger';
31
+ *
32
+ * const http = logger.scope('HTTP');
33
+ * http.badge('OUTBOUND').info('Request enviada');
34
+ * // salida: [HTTP] [OUTBOUND] Request enviada
35
+ *
36
+ * @example
37
+ * // Anidar contextos dentro de un scope (el prefijo se compone con ':')
38
+ * const retry = http.context('retry');
39
+ * retry.run(() => http.warn('Reintentando petición'));
40
+ * // salida: [HTTP:retry] Reintentando petición
41
+ *
42
+ * @see {@link Logger.scope}
43
+ * @see {@link APILogger}
44
+ * @see {@link ComponentLogger}
45
+ * @see {@link ContextLogger}
46
+ */
17
47
  var ScopedLogger = class {
18
48
  parent;
19
49
  scopeName;
20
50
  badgeList = [];
21
51
  contextStack = [];
22
52
  _timers;
53
+ /**
54
+ * Construye un ScopedLogger vinculado a un {@link Logger} padre.
55
+ *
56
+ * Los clientes no deben llamar a este constructor directamente: usen
57
+ * `logger.scope(name)`, que configura correctamente la instancia.
58
+ *
59
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
60
+ * @param {string} scopeName - Etiqueta del scope; se renderiza como
61
+ * prefijo `[scopeName]` en cada línea.
62
+ */
23
63
  constructor(parent, scopeName) {
24
64
  this.parent = parent;
25
65
  this.scopeName = scopeName;
@@ -38,31 +78,125 @@ var ScopedLogger = class {
38
78
  if (this.contextStack.length === 0) return this.scopeName;
39
79
  return [this.scopeName, ...this.contextStack].join(":");
40
80
  }
81
+ /**
82
+ * Reemplaza la lista actual de badges por la pasada y la aplica a todos
83
+ * los mensajes posteriores de este scope.
84
+ *
85
+ * @param {string[]} badges - Etiquetas a mostrar como badges adyacentes
86
+ * al prefijo (p. ej. `['OUTBOUND', 'CACHED']`).
87
+ * @returns {this} La misma instancia, para encadenar llamadas.
88
+ *
89
+ * @example
90
+ * logger.scope('HTTP').badges(['OUTBOUND', 'CACHED']).info('Cache hit');
91
+ * // salida: [HTTP] [OUTBOUND] [CACHED] Cache hit
92
+ *
93
+ * @see {@link badge} para añadir sin reemplazar los existentes.
94
+ * @see {@link clearBadges} para vaciar la lista.
95
+ */
41
96
  badges(badges) {
42
97
  this.badgeList = [...badges];
43
98
  return this;
44
99
  }
100
+ /**
101
+ * Añade un badge al scope de forma idempotente (no lo duplica si ya existe).
102
+ *
103
+ * @param {string} badge - Etiqueta a añadir a la lista de badges.
104
+ * @returns {this} La misma instancia, para encadenar llamadas.
105
+ *
106
+ * @example
107
+ * logger.scope('API')
108
+ * .badge('OUTBOUND')
109
+ * .badge('RETRY')
110
+ * .warn('Reintentando');
111
+ * // salida: [API] [OUTBOUND] [RETRY] Reintentando
112
+ */
45
113
  badge(badge) {
46
114
  if (!this.badgeList.includes(badge)) this.badgeList.push(badge);
47
115
  return this;
48
116
  }
117
+ /**
118
+ * Vacía la lista de badges del scope.
119
+ *
120
+ * @returns {this} La misma instancia, para encadenar llamadas.
121
+ *
122
+ * @example
123
+ * const http = logger.scope('HTTP');
124
+ * http.badge('OUTBOUND').info('uno');
125
+ * http.clearBadges().info('dos');
126
+ * // [HTTP] [OUTBOUND] uno / [HTTP] dos
127
+ */
49
128
  clearBadges() {
50
129
  this.badgeList = [];
51
130
  return this;
52
131
  }
132
+ /**
133
+ * Aplica un theme preset al logger padre. El preset afecta a toda la
134
+ * instancia raíz (no solo a este scope) porque el style es compartido.
135
+ *
136
+ * @param {string} presetName - Nombre del preset registrado en el StyleManager.
137
+ * @returns {this} La misma instancia, para encadenar llamadas.
138
+ *
139
+ * @example
140
+ * logger.scope('UI').style('cyberpunk').info('neon');
141
+ * @see {@link Logger.setTheme}
142
+ */
53
143
  style(presetName) {
54
144
  this.parent.setTheme(presetName);
55
145
  return this;
56
146
  }
147
+ /**
148
+ * Crea un {@link ContextLogger} vinculado a este scope. Los contextos se
149
+ * apilan en el prefijo separados por `:`, permitiendo agrupar bloques de
150
+ * logs relacionados (reintentos, sub-etapas, etc.) sin `console.group`.
151
+ *
152
+ * @param {string} contextName - Nombre del contexto a apilar.
153
+ * @returns {ContextLogger} Handler con `run`, `runAsync`, `start`/`end`.
154
+ *
155
+ * @example
156
+ * const retry = logger.scope('HTTP').context('retry');
157
+ * retry.run(() => logger.warn('Reintentando'));
158
+ * // salida: [HTTP:retry] Reintentando
159
+ * @see {@link ContextLogger}
160
+ */
57
161
  context(contextName) {
58
162
  return new ContextLogger(this, contextName);
59
163
  }
164
+ /**
165
+ * Inicia un timer etiquetado bajo el namespace `<scopeName>:<label>`.
166
+ * El label es local a este scope, así que dos scopes pueden reutilizar el
167
+ * mismo nombre sin colisión.
168
+ *
169
+ * @param {string} label - Identificador del timer.
170
+ *
171
+ * @example
172
+ * const http = logger.scope('HTTP');
173
+ * http.time('request');
174
+ * // ... trabajo ...
175
+ * http.timeEnd('request'); // imprime "Timer: request - 12.34ms"
176
+ * @see {@link timeEnd}
177
+ */
60
178
  time(label) {
61
179
  this.timers.set(label, {
62
180
  label: `${this.scopeName}:${label}`,
63
181
  startTime: performance.now()
64
182
  });
65
183
  }
184
+ /**
185
+ * Detiene un timer previamente iniciado con {@link time} y registra la
186
+ * duración con nivel `success`. Si el label no existe, emite un `warn`
187
+ * y devuelve `undefined`.
188
+ *
189
+ * @param {string} label - Mismo label pasado a {@link time}.
190
+ * @returns {number | undefined} Milisegundos transcurridos, o `undefined`
191
+ * si el timer no estaba registrado.
192
+ *
193
+ * @example
194
+ * const http = logger.scope('HTTP');
195
+ * http.time('fetch');
196
+ * await fetch(url);
197
+ * const ms = http.timeEnd('fetch');
198
+ * if (ms && ms > 1000) http.warn('Latencia alta');
199
+ */
66
200
  timeEnd(label) {
67
201
  const timer = this.timers.get(label);
68
202
  if (!timer) {
@@ -74,118 +208,447 @@ var ScopedLogger = class {
74
208
  this.success(`Timer: ${label} - ${elapsed.toFixed(2)}ms`);
75
209
  return elapsed;
76
210
  }
211
+ /**
212
+ * Emite un mensaje a nivel `debug` con los bindings actuales del scope.
213
+ *
214
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales (objetos,
215
+ * errores, etc.) serializados igual que en el logger raíz.
216
+ *
217
+ * @example
218
+ * logger.scope('DB').debug('query', { sql, params });
219
+ */
77
220
  debug(...args) {
78
221
  this.parent.logWithBindings(this.getBindings(), "debug", ...args);
79
222
  }
223
+ /**
224
+ * Emite un mensaje a nivel `info` con los bindings actuales del scope.
225
+ *
226
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
227
+ *
228
+ * @example
229
+ * logger.scope('AUTH').info('Login exitoso', { userId });
230
+ */
80
231
  info(...args) {
81
232
  this.parent.logWithBindings(this.getBindings(), "info", ...args);
82
233
  }
234
+ /**
235
+ * Emite un mensaje a nivel `warn` con los bindings actuales del scope.
236
+ *
237
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
238
+ *
239
+ * @example
240
+ * logger.scope('CACHE').warn('Cache miss', { key });
241
+ */
83
242
  warn(...args) {
84
243
  this.parent.logWithBindings(this.getBindings(), "warn", ...args);
85
244
  }
245
+ /**
246
+ * Emite un mensaje a nivel `error` con los bindings actuales del scope.
247
+ *
248
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales (típicamente
249
+ * un `Error` o contexto del fallo).
250
+ *
251
+ * @example
252
+ * logger.scope('DB').error('Conexión rechazada', err);
253
+ */
86
254
  error(...args) {
87
255
  this.parent.logWithBindings(this.getBindings(), "error", ...args);
88
256
  }
257
+ /**
258
+ * Emite un mensaje con badge visual `SUCCESS` a nivel `info`. Úselo para
259
+ * hitos positivos dentro del scope (conexión establecida, sync completo,
260
+ * commit aplicado).
261
+ *
262
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
263
+ *
264
+ * @example
265
+ * logger.scope('SYNC').success('Sincronización completa', { count: 42 });
266
+ */
89
267
  success(...args) {
90
268
  const bindings = this.getBindings();
91
269
  this.parent.logWithBindingsAndTag(bindings, "info", "success", ...args);
92
270
  }
271
+ /**
272
+ * Emite un mensaje a nivel `critical` con los bindings actuales del scope.
273
+ * Reservado para fallos que detienen el flujo de la aplicación.
274
+ *
275
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
276
+ *
277
+ * @example
278
+ * logger.scope('PAY').critical('Pasarela inaccesible', err);
279
+ */
93
280
  critical(...args) {
94
281
  this.parent.logWithBindings(this.getBindings(), "critical", ...args);
95
282
  }
283
+ /**
284
+ * Emite un mensaje a nivel `trace` (verbosidad máxima) con los bindings
285
+ * actuales del scope. Solo aparece si la verbosity global lo permite.
286
+ *
287
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
288
+ *
289
+ * @example
290
+ * logger.scope('NET').trace('packet', { bytes });
291
+ */
96
292
  trace(...args) {
97
293
  this.parent.logWithBindings(this.getBindings(), "trace", ...args);
98
294
  }
99
- /** @see Logger.step */
295
+ /**
296
+ * Emite un point-span con el scope de este logger como
297
+ * `SpanRecord.scope`. Ver {@link Logger.event}.
298
+ *
299
+ * @param {string} name - Nombre del evento.
300
+ * @param {SpanAttributes} [attributes] - Attributes del span.
301
+ *
302
+ * @example
303
+ * logger.scope('BUILD').event('step.done', { step: 'compile' });
304
+ */
305
+ event(name, attributes) {
306
+ this.parent._emitSpanEvent(name, attributes, this.getScopePrefix());
307
+ }
308
+ span(name, fnOrAttributes, maybeFn) {
309
+ const { attributes, fn } = resolveSpanArgs(fnOrAttributes, maybeFn);
310
+ return this.parent._runSpan(name, attributes, this.getScopePrefix(), fn);
311
+ }
312
+ /**
313
+ * Inicia un span externally-ended etiquetado con el scope de este
314
+ * logger. Ver {@link Logger.startSpan}.
315
+ *
316
+ * @param {string} name - Nombre de la operación.
317
+ * @param {SpanAttributes} [attributes] - Attributes iniciales.
318
+ * @returns {Span} Handle con `set`/`end`/`fail`.
319
+ */
320
+ startSpan(name, attributes) {
321
+ return this.parent._startSpan(name, attributes, this.getScopePrefix());
322
+ }
323
+ /**
324
+ * Delegación a {@link Logger.step}: dibuja una barra de progreso discreta
325
+ * `current/total` para este scope.
326
+ *
327
+ * @param {number} current - Paso actual (1-indexed).
328
+ * @param {number} total - Total de pasos.
329
+ * @param {string} message - Texto mostrado junto al contador.
330
+ * @see {@link Logger.step}
331
+ */
100
332
  step(current, total, message) {
101
333
  this.parent.step(current, total, message);
102
334
  }
103
- /** @see Logger.header */
335
+ /**
336
+ * Delegación a {@link Logger.header}: imprime un título con separadores visuales.
337
+ *
338
+ * @param {string} title - Texto del título.
339
+ * @param {string} [subtitle] - Subtítulo opcional bajo el título.
340
+ * @see {@link Logger.header}
341
+ */
104
342
  header(title, subtitle) {
105
343
  this.parent.header(title, subtitle);
106
344
  }
107
- /** @see Logger.divider */
345
+ /**
346
+ * Delegación a {@link Logger.divider}: imprime una línea separadora horizontal.
347
+ * @see {@link Logger.divider}
348
+ */
108
349
  divider() {
109
350
  this.parent.divider();
110
351
  }
111
- /** @see Logger.blank */
352
+ /**
353
+ * Delegación a {@link Logger.blank}: inserta una línea en blanco.
354
+ * @see {@link Logger.blank}
355
+ */
112
356
  blank() {
113
357
  this.parent.blank();
114
358
  }
115
- /** @see Logger.box */
359
+ /**
360
+ * Delegación a {@link Logger.box}: dibuja un recuadro ANSI alrededor de `content`.
361
+ *
362
+ * @param {string} content - Texto a enmarcar.
363
+ * @param {IBoxOptions} [options] - Opciones de estilo del box.
364
+ * @see {@link Logger.box}
365
+ */
116
366
  box(content, options) {
117
367
  this.parent.box(content, options);
118
368
  }
119
- /** @see Logger.cliTable */
369
+ /**
370
+ * Delegación a {@link Logger.cliTable}: renderiza `rows` como tabla ASCII.
371
+ *
372
+ * @param {Record<string, unknown>[]} rows - Filas a mostrar.
373
+ * @param {ITableOptions} [options] - Opciones de columnas y estilo.
374
+ * @see {@link Logger.cliTable}
375
+ */
120
376
  cliTable(rows, options) {
121
377
  this.parent.cliTable(rows, options);
122
378
  }
123
- /** @see Logger.spinner */
379
+ /**
380
+ * Delegación a {@link Logger.spinner}: arranca un spinner con `message`.
381
+ *
382
+ * @param {string} message - Texto a mostrar al lado del spinner.
383
+ * @returns {ISpinnerHandle} Handle para detener/actualizar el spinner.
384
+ * @see {@link Logger.spinner}
385
+ */
124
386
  spinner(message) {
125
387
  return this.parent.spinner(message);
126
388
  }
127
- /** @see Logger.setCLILevel */
389
+ /**
390
+ * Delegación a {@link Logger.setCLILevel}: ajusta el nivel mínimo de las
391
+ * primitivas CLI visibles.
392
+ *
393
+ * @param {CLILogLevel} level - Nivel CLI (`silent` … `verbose`).
394
+ * @see {@link Logger.setCLILevel}
395
+ */
128
396
  setCLILevel(level) {
129
397
  this.parent.setCLILevel(level);
130
398
  }
399
+ /**
400
+ * Apila un contexto en el prefijo del scope. Invocado por
401
+ * {@link ContextLogger}; los clientes no deben llamarlo directamente.
402
+ *
403
+ * @param {string} context - Nombre del contexto a apilar.
404
+ * @internal
405
+ */
131
406
  _pushContext(context) {
132
407
  this.contextStack.push(context);
133
408
  }
409
+ /**
410
+ * Desapila el último contexto del prefijo del scope. Invocado por
411
+ * {@link ContextLogger}; los clientes no deben llamarlo directamente.
412
+ *
413
+ * @internal
414
+ */
134
415
  _popContext() {
135
416
  this.contextStack.pop();
136
417
  }
137
418
  };
419
+ /**
420
+ * Logger especializado para llamadas a APIs y servicios externos.
421
+ *
422
+ * Extiende {@link ScopedLogger} pre-seteando el badge `API` y exponiendo
423
+ * atajos para eventos típicos de integración: llamadas lentas ({@link slow}),
424
+ * rate limiting ({@link rateLimit}), fallos de autenticación ({@link auth}) y
425
+ * APIs deprecadas ({@link deprecated}).
426
+ *
427
+ * Se obtiene con `logger.api(name)` y no se construye directamente.
428
+ *
429
+ * @example
430
+ * import logger from '@mks2508/better-logger';
431
+ *
432
+ * const stripe = logger.api('Stripe');
433
+ * stripe.info('Consultando customer', { id });
434
+ * // salida: [API:Stripe] [API] Consultando customer
435
+ *
436
+ * stripe.slow('customer.retrieve', 1250);
437
+ * // salida: [API:Stripe] [API] [SLOW] customer.retrieve (1250ms)
438
+ *
439
+ * @see {@link Logger.api}
440
+ * @see {@link ScopedLogger}
441
+ */
138
442
  var APILogger = class extends ScopedLogger {
443
+ /**
444
+ * Construye un APILogger con scope `API:<apiName>` y badge `API` ya aplicado.
445
+ *
446
+ * Los clientes deben usar `logger.api(name)`.
447
+ *
448
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
449
+ * @param {string} apiName - Nombre del servicio/API (se prefija con `API:`).
450
+ */
139
451
  constructor(parent, apiName) {
140
452
  super(parent, `API:${apiName}`);
141
453
  this.badge("API");
142
454
  }
455
+ /**
456
+ * Registra una llamada lenta con badge `SLOW` a nivel `warn`.
457
+ *
458
+ * @param {string} message - Descripción de la operación lenta.
459
+ * @param {number} [duration] - Duración medida en ms; si se pasa, se
460
+ * anexa al mensaje como `(Nms)`.
461
+ *
462
+ * @example
463
+ * const t0 = performance.now();
464
+ * await stripe.customers.retrieve(id);
465
+ * logger.api('Stripe').slow('retrieve', performance.now() - t0);
466
+ */
143
467
  slow(message, duration) {
144
468
  this.badge("SLOW");
145
469
  const msg = duration ? `${message} (${duration}ms)` : message;
146
470
  this.warn(msg);
147
471
  }
472
+ /**
473
+ * Registra un evento de rate limiting (HTTP 429) con badge `RATE_LIMIT`.
474
+ *
475
+ * @param {string} message - Detalle del límite golpeado.
476
+ *
477
+ * @example
478
+ * logger.api('GitHub').rateLimit('Secondary rate limit on /search');
479
+ */
148
480
  rateLimit(message) {
149
481
  this.badge("RATE_LIMIT");
150
482
  this.warn(message);
151
483
  }
484
+ /**
485
+ * Registra un fallo de autenticación (401/403) con badge `AUTH` a nivel
486
+ * `error`.
487
+ *
488
+ * @param {string} message - Detalle del fallo de credenciales/token.
489
+ *
490
+ * @example
491
+ * logger.api('OAuth').auth('Token expirado');
492
+ */
152
493
  auth(message) {
153
494
  this.badge("AUTH");
154
495
  this.error(message);
155
496
  }
497
+ /**
498
+ * Marca una API como deprecada con badge `DEPRECATED` a nivel `warn`.
499
+ *
500
+ * @param {string} message - Mensaje guiando a la migración (endpoint
501
+ * alternativo, versión retirada, etc.).
502
+ *
503
+ * @example
504
+ * logger.api('Legacy').deprecated('Usar v3; v2 se retira en Q4');
505
+ */
156
506
  deprecated(message) {
157
507
  this.badge("DEPRECATED");
158
508
  this.warn(message);
159
509
  }
160
510
  };
511
+ /**
512
+ * Logger para componentes UI, módulos o cualquier unidad con ciclo de vida.
513
+ *
514
+ * Extiende {@link ScopedLogger} pre-seteando el badge `COMPONENT` y exponiendo
515
+ * atajos para eventos típicos: {@link lifecycle}, {@link stateChange} y
516
+ * {@link propsChange}.
517
+ *
518
+ * Se obtiene con `logger.component(name)` y no se construye directamente.
519
+ *
520
+ * @example
521
+ * import logger from '@mks2508/better-logger';
522
+ *
523
+ * const cart = logger.component('Cart');
524
+ * cart.lifecycle('mount');
525
+ * // salida: [Cart] [COMPONENT] [LIFECYCLE] mount
526
+ *
527
+ * cart.stateChange('empty', 'has-items', { count: 3 });
528
+ * // salida: [Cart] [COMPONENT] [STATE] empty → has-items { count: 3 }
529
+ *
530
+ * @see {@link Logger.component}
531
+ * @see {@link ScopedLogger}
532
+ */
161
533
  var ComponentLogger = class extends ScopedLogger {
534
+ /**
535
+ * Construye un ComponentLogger con badge `COMPONENT` ya aplicado.
536
+ *
537
+ * Los clientes deben usar `logger.component(name)`.
538
+ *
539
+ * @param {Logger} parent - Logger raíz al que se delegan los mensajes.
540
+ * @param {string} componentName - Nombre del componente (scope label).
541
+ */
162
542
  constructor(parent, componentName) {
163
543
  super(parent, componentName);
164
544
  this.badge("COMPONENT");
165
545
  }
546
+ /**
547
+ * Registra un evento de ciclo de vida con badge `LIFECYCLE` a nivel `info`.
548
+ *
549
+ * @param {string} event - Nombre del evento (`mount`, `unmount`,
550
+ * `update`, ...).
551
+ * @param {string} [message] - Detalle opcional; si se omite, solo se
552
+ * registra el nombre del evento.
553
+ *
554
+ * @example
555
+ * logger.component('Cart').lifecycle('mount', 'Modal abierto');
556
+ */
166
557
  lifecycle(event, message) {
167
558
  this.badge("LIFECYCLE");
168
559
  const msg = message ? `${event}: ${message}` : event;
169
560
  this.info(msg);
170
561
  }
562
+ /**
563
+ * Registra una transición de estado con badge `STATE` a nivel `info`.
564
+ *
565
+ * @param {string} from - Estado previo.
566
+ * @param {string} to - Estado nuevo.
567
+ * @param {unknown} [data] - Payload opcional asociado a la transición.
568
+ *
569
+ * @example
570
+ * const fsm = logger.component('FSM');
571
+ * fsm.stateChange('idle', 'loading');
572
+ * fsm.stateChange('loading', 'success', { items: 3 });
573
+ */
171
574
  stateChange(from, to, data) {
172
575
  this.badge("STATE");
173
576
  const msg = `${from} → ${to}`;
174
577
  if (data) this.info(msg, data);
175
578
  else this.info(msg);
176
579
  }
580
+ /**
581
+ * Registra cambios de props/debug del componente con badge `PROPS` a nivel
582
+ * `debug`.
583
+ *
584
+ * @param {Record<string, unknown>} changes - Mapa prop → valor (típicamente
585
+ * el diff de props entre renders).
586
+ *
587
+ * @example
588
+ * logger.component('Cart').propsChange({ itemCount: 5, currency: 'EUR' });
589
+ */
177
590
  propsChange(changes) {
178
591
  this.badge("PROPS");
179
592
  this.debug("Props changed:", changes);
180
593
  }
181
594
  };
595
+ /**
596
+ * Handler de contexto apilable sobre un {@link ScopedLogger}.
597
+ *
598
+ * Permite agrupar bloques de logs bajo un sub-prefijo separado por `:`,
599
+ * manteniendo la correlación visual sin necesidad de `console.group`. El
600
+ * prefijo compuesto se forma como `<scopeName>:<contextName>`.
601
+ *
602
+ * Se crea con `scopedLogger.context(name)`. El patrón idiomático es
603
+ * {@link run}/{@link runAsync} (auto push/pop con try/finally); {@link start}
604
+ * y {@link end} permiten control manual cuando el bloque no cierra
605
+ * léxicamente (event handlers distribuidos, promesas de larga duración).
606
+ *
607
+ * @example
608
+ * import logger from '@mks2508/better-logger';
609
+ *
610
+ * const http = logger.scope('HTTP');
611
+ *
612
+ * // Bloque síncrono auto-cerrado
613
+ * http.context('retry').run(() => {
614
+ * http.warn('Reintentando petición');
615
+ * });
616
+ * // salida: [HTTP:retry] Reintentando petición
617
+ *
618
+ * // Bloque async auto-cerrado
619
+ * await http.context('refresh').runAsync(async () => {
620
+ * await refreshToken();
621
+ * http.info('Token refrescado');
622
+ * });
623
+ *
624
+ * @see {@link ScopedLogger.context}
625
+ */
182
626
  var ContextLogger = class {
183
627
  parentLogger;
184
628
  contextName;
629
+ /**
630
+ * @param {ScopedLogger} parentLogger - Scope sobre el que se apila el contexto.
631
+ * @param {string} contextName - Sub-prefijo a apilar en el scope padre.
632
+ */
185
633
  constructor(parentLogger, contextName) {
186
634
  this.parentLogger = parentLogger;
187
635
  this.contextName = contextName;
188
636
  }
637
+ /**
638
+ * Ejecuta `fn` síncrona dentro del contexto, garantizando el pop del
639
+ * prefijo incluso si `fn` lanza. El contexto solo está activo durante la
640
+ * ejecución de `fn`.
641
+ *
642
+ * @typeParam T - Tipo de retorno de `fn`.
643
+ * @param {() => T} fn - Función a ejecutar bajo el contexto.
644
+ * @returns {T} Lo que devuelva `fn`.
645
+ * @throws {unknown} Relanza cualquier excepción de `fn` tras desapilar.
646
+ *
647
+ * @example
648
+ * logger.scope('HTTP').context('warmup').run(() => {
649
+ * logger.info('Pre-cargando caché');
650
+ * });
651
+ */
189
652
  run(fn) {
190
653
  this.parentLogger._pushContext(this.contextName);
191
654
  try {
@@ -194,6 +657,21 @@ var ContextLogger = class {
194
657
  this.parentLogger._popContext();
195
658
  }
196
659
  }
660
+ /**
661
+ * Variante async de {@link run}: mantiene el contexto activo mientras se
662
+ * awaiting la promesa de `fn`, incluyendo awaits internos.
663
+ *
664
+ * @typeParam T - Tipo resuelto por la promesa de `fn`.
665
+ * @param {() => Promise<T>} fn - Función async a ejecutar bajo el contexto.
666
+ * @returns {Promise<T>} Promesa que resuelve al valor de `fn`.
667
+ * @throws {unknown} Relanza cualquier rechazo de `fn` tras desapilar.
668
+ *
669
+ * @example
670
+ * await logger.scope('HTTP').context('fetch').runAsync(async () => {
671
+ * const r = await fetch(url);
672
+ * logger.info('Recibido', { status: r.status });
673
+ * });
674
+ */
197
675
  async runAsync(fn) {
198
676
  this.parentLogger._pushContext(this.contextName);
199
677
  try {
@@ -202,27 +680,80 @@ var ContextLogger = class {
202
680
  this.parentLogger._popContext();
203
681
  }
204
682
  }
683
+ /**
684
+ * Apila el contexto manualmente. Útil cuando el bloque que lo consume no
685
+ * cierra léxicamente (event handlers, timeouts, streams). Debe emparejarse
686
+ * con un {@link end} posterior; olvidarlo deja el prefijo contaminado para
687
+ * los logs siguientes del scope.
688
+ *
689
+ * @example
690
+ * const ctx = logger.scope('WS').context('subscribe');
691
+ * socket.onopen = () => { ctx.start(); ctx.info('connected'); };
692
+ * socket.onclose = () => { ctx.info('disconnected'); ctx.end(); };
693
+ * @see {@link end}
694
+ */
205
695
  start() {
206
696
  this.parentLogger._pushContext(this.contextName);
207
697
  }
698
+ /**
699
+ * Desapila el último contexto abierto con {@link start}.
700
+ *
701
+ * @see {@link start}
702
+ */
208
703
  end() {
209
704
  this.parentLogger._popContext();
210
705
  }
706
+ /**
707
+ * Atajo a `scopedLogger.debug(...)`. El contexto se aplica al prefijo del
708
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
709
+ *
710
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
711
+ */
211
712
  debug(...args) {
212
713
  this.parentLogger.debug(...args);
213
714
  }
715
+ /**
716
+ * Atajo a `scopedLogger.info(...)`. El contexto se aplica al prefijo del
717
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
718
+ *
719
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
720
+ */
214
721
  info(...args) {
215
722
  this.parentLogger.info(...args);
216
723
  }
724
+ /**
725
+ * Atajo a `scopedLogger.warn(...)`. El contexto se aplica al prefijo del
726
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
727
+ *
728
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
729
+ */
217
730
  warn(...args) {
218
731
  this.parentLogger.warn(...args);
219
732
  }
733
+ /**
734
+ * Atajo a `scopedLogger.error(...)`. El contexto se aplica al prefijo del
735
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
736
+ *
737
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
738
+ */
220
739
  error(...args) {
221
740
  this.parentLogger.error(...args);
222
741
  }
742
+ /**
743
+ * Atajo a `scopedLogger.success(...)`. El contexto se aplica al prefijo del
744
+ * scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
745
+ *
746
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
747
+ */
223
748
  success(...args) {
224
749
  this.parentLogger.success(...args);
225
750
  }
751
+ /**
752
+ * Atajo a `scopedLogger.critical(...)`. El contexto se aplica al prefijo
753
+ * del scope padre solo si se invoca dentro de un bloque {@link run}/{@link start}.
754
+ *
755
+ * @param {...unknown[]} args - Mensaje y argumentos adicionales.
756
+ */
226
757
  critical(...args) {
227
758
  this.parentLogger.critical(...args);
228
759
  }
@@ -230,7 +761,34 @@ var ContextLogger = class {
230
761
  //#endregion
231
762
  //#region src/cli/CommandProcessor.ts
232
763
  /**
233
- * CLI command processor
764
+ * Procesador central del CLI del logger. Resuelve nombres de comando (con
765
+ * aliases), despacha ejecución, mantiene historial acotado (max 100 entradas)
766
+ * y soporta un sistema de plugins para extensión de terceros.
767
+ *
768
+ * No es un binario standalone: se invoca desde la consola del navegador vía
769
+ * `window.cli("<command>")` (modo interactivo habilitado por
770
+ * {@link enterInteractiveMode}) o desde código vía `logger.cli()`. El
771
+ * constructor no registra ningún comando por defecto — usar
772
+ * {@link createDefaultCLI} para obtener una instancia con los 8 comandos
773
+ * estándar ya cargados.
774
+ *
775
+ * @example
776
+ * ```ts
777
+ * const cli = createDefaultCLI();
778
+ * await cli.processCommand('/themes', logger);
779
+ * await cli.processCommand('/config theme=neon', logger);
780
+ * ```
781
+ *
782
+ * @example
783
+ * ```ts
784
+ * // Modo interactivo: expone `window.cli` en el navegador
785
+ * cli.enterInteractiveMode(logger);
786
+ * // Desde la devtools: cli('help') → procesa '/help'
787
+ * ```
788
+ *
789
+ * @see {@link createDefaultCLI}
790
+ * @see {@link ICommand}
791
+ * @see {@link ICLIPlugin}
234
792
  */
235
793
  var CommandProcessor = class {
236
794
  commands = /* @__PURE__ */ new Map();
@@ -240,14 +798,26 @@ var CommandProcessor = class {
240
798
  maxHistorySize = 100;
241
799
  isInteractiveMode = false;
242
800
  /**
243
- * Register a command
801
+ * Registra un comando. Si el comando declara `aliases`, también se indexan
802
+ * para resolución. Un comando con el mismo `name` sobreescribe al previo.
803
+ *
804
+ * @param {ICommand} command - Comando a registrar.
805
+ * @see {@link ICommand}
244
806
  */
245
807
  registerCommand(command) {
246
808
  this.commands.set(command.name, command);
247
809
  if (command.aliases) for (const alias of command.aliases) this.aliases.set(alias, command.name);
248
810
  }
249
811
  /**
250
- * Register a plugin
812
+ * Registra un plugin: indexa todos sus commands y, si el plugin define
813
+ * `initialize`, lo invoca con el processor y el logger. Los comandos del
814
+ * plugin se registran vía {@link registerCommand} y sus aliases quedan
815
+ * resolvibles igual que los directos.
816
+ *
817
+ * @param {ICLIPlugin} plugin - Plugin a registrar.
818
+ * @param {Logger} [logger] - Logger activo; requerido solo si el plugin define `initialize`.
819
+ * @throws {Error} Si ya existe un plugin registrado con el mismo `name`.
820
+ * @see {@link unregisterPlugin}
251
821
  */
252
822
  registerPlugin(plugin, logger) {
253
823
  if (this.plugins.has(plugin.name)) throw new Error(`Plugin ${plugin.name} is already registered`);
@@ -256,7 +826,12 @@ var CommandProcessor = class {
256
826
  if (plugin.initialize && logger) plugin.initialize(this, logger);
257
827
  }
258
828
  /**
259
- * Unregister a plugin
829
+ * Desregistra un plugin por nombre: elimina todos sus commands (y los
830
+ * aliases que aportasen), invoca su hook `cleanup` si existe y lo quita
831
+ * del registry. No-op si el nombre no existe.
832
+ *
833
+ * @param {string} pluginName - Nombre del plugin a desregistrar.
834
+ * @see {@link registerPlugin}
260
835
  */
261
836
  unregisterPlugin(pluginName) {
262
837
  const plugin = this.plugins.get(pluginName);
@@ -269,13 +844,20 @@ var CommandProcessor = class {
269
844
  this.plugins.delete(pluginName);
270
845
  }
271
846
  /**
272
- * Get all registered commands
847
+ * Lista todos los commands registrados (directamente o vía plugins).
848
+ * No incluye aliases.
849
+ *
850
+ * @returns {ICommand[]} Snapshot array de los commands registrados.
273
851
  */
274
852
  getCommands() {
275
853
  return Array.from(this.commands.values());
276
854
  }
277
855
  /**
278
- * Get a specific command
856
+ * Resuelve un comando por nombre canónico o alias. Devuelve `undefined`
857
+ * si no existe ninguno que matchee.
858
+ *
859
+ * @param {string} name - Nombre canónico o alias del comando.
860
+ * @returns {ICommand | undefined} El comando resuelto, o `undefined`.
279
861
  */
280
862
  getCommand(name) {
281
863
  let command = this.commands.get(name);
@@ -284,25 +866,38 @@ var CommandProcessor = class {
284
866
  if (aliasTarget) return this.commands.get(aliasTarget);
285
867
  }
286
868
  /**
287
- * Get command history
869
+ * Devuelve una copia del historial de comandos ejecutados (más recientes
870
+ * primero). Acotado a 100 entradas por {@link maxHistorySize}; las más
871
+ * viejas se descartan al insertar nuevas.
872
+ *
873
+ * @returns {HistoryEntry[]} Snapshot del historial; mutar el array devuelto
874
+ * no afecta al estado interno del processor.
288
875
  */
289
876
  getHistory() {
290
877
  return [...this.history];
291
878
  }
292
879
  /**
293
- * Clear command history
880
+ * Vacía el historial de comandos en memoria.
294
881
  */
295
882
  clearHistory() {
296
883
  this.history = [];
297
884
  }
298
885
  /**
299
- * Get registered plugins
886
+ * Lista los plugins actualmente registrados.
887
+ *
888
+ * @returns {ICLIPlugin[]} Snapshot array de plugins activos.
300
889
  */
301
890
  getPlugins() {
302
891
  return Array.from(this.plugins.values());
303
892
  }
304
893
  /**
305
- * Enter interactive mode
894
+ * Activa el modo interactivo. Marca el flag interno y, si se ejecuta en
895
+ * navegador, expone `window.cli(command)` para invocar comandos desde la
896
+ * devtools sin prefijo `/` (se añade automáticamente al input).
897
+ *
898
+ * @param {Logger} logger - Logger activo (emite el mensaje de bienvenida
899
+ * con hint sobre `cli(...)` en browser).
900
+ * @see {@link exitInteractiveMode}
306
901
  */
307
902
  enterInteractiveMode(logger) {
308
903
  this.isInteractiveMode = true;
@@ -310,13 +905,22 @@ var CommandProcessor = class {
310
905
  if (typeof window !== "undefined") this.setupBrowserInteractiveMode(logger);
311
906
  }
312
907
  /**
313
- * Exit interactive mode
908
+ * Desactiva el flag de modo interactivo. Nota: no elimina el `window.cli`
909
+ * que {@link enterInteractiveMode} haya expuesto en el navegador — el
910
+ * handler global sigue vivo hasta reload.
911
+ *
912
+ * @see {@link enterInteractiveMode}
314
913
  */
315
914
  exitInteractiveMode() {
316
915
  this.isInteractiveMode = false;
317
916
  }
318
917
  /**
319
- * Setup browser interactive mode
918
+ * Instala `window.cli(command)` como wrapper delgado alrededor de
919
+ * {@link processCommand}, prefijando `/` automáticamente. Solo se invoca
920
+ * desde {@link enterInteractiveMode} cuando `window` está disponible.
921
+ *
922
+ * @internal
923
+ * @param logger - Logger activo, reenviado a cada invocación.
320
924
  */
321
925
  setupBrowserInteractiveMode(logger) {
322
926
  window.cli = (commandString) => {
@@ -325,7 +929,20 @@ var CommandProcessor = class {
325
929
  logger.info("💡 Use cli(\"command\") to execute CLI commands in browser console.");
326
930
  }
327
931
  /**
328
- * Process a CLI command
932
+ * Parsea y ejecuta un comando. El formato esperado es `/name args...`:
933
+ * split por espacios, primer token = nombre del comando, resto = args
934
+ * (re-joined con espacios). Si el comando no existe, loguea el error y
935
+ * sugiere similares vía {@link getSuggestions} ("Did you mean: ...?").
936
+ *
937
+ * Toda invocación (válida o no) se registra en el historial con flag de
938
+ * éxito/fallo según si `execute` resolvió o throweó.
939
+ *
940
+ * @param {string} commandString - Comando completo, debe empezar con `/`.
941
+ * @param {Logger} logger - Logger activo para output y errores.
942
+ * @returns {Promise<void>} Resuelve cuando el comando termina (sync o async).
943
+ * Nunca rechaza: los errores de `execute` se capturan y se loguean.
944
+ * @see {@link ICommand.execute}
945
+ * @see {@link getSuggestions}
329
946
  */
330
947
  async processCommand(commandString, logger) {
331
948
  if (!commandString.startsWith("/")) {
@@ -353,7 +970,12 @@ var CommandProcessor = class {
353
970
  }
354
971
  }
355
972
  /**
356
- * Add command to history
973
+ * Inserta una entrada al frente del historial y trunca a
974
+ * {@link maxHistorySize} (100) si hace falta.
975
+ *
976
+ * @internal
977
+ * @param command - String crudo del comando ejecutado.
978
+ * @param success - Si la ejecución tuvo éxito.
357
979
  */
358
980
  addToHistory(command, success) {
359
981
  this.history.unshift({
@@ -364,7 +986,12 @@ var CommandProcessor = class {
364
986
  if (this.history.length > this.maxHistorySize) this.history = this.history.slice(0, this.maxHistorySize);
365
987
  }
366
988
  /**
367
- * Get command suggestions for partial matches
989
+ * Devuelve nombres de comando que empiezan con el prefijo dado. Alimente
990
+ * el hint "Did you mean" de {@link processCommand} cuando un comando no
991
+ * se encuentra. Match por `startsWith` (no fuzzy).
992
+ *
993
+ * @param {string} partial - Prefijo parcial tipeado por el usuario.
994
+ * @returns {string[]} Nombres canónicos que matchean; aliases excluidos.
368
995
  */
369
996
  getSuggestions(partial) {
370
997
  return Array.from(this.commands.keys()).filter((name) => name.startsWith(partial));
@@ -373,12 +1000,47 @@ var CommandProcessor = class {
373
1000
  //#endregion
374
1001
  //#region src/cli/commands/ConfigCommand.ts
375
1002
  /**
376
- * Configuration command handler
1003
+ * Comando `/config` del CLI runtime del {@link Logger}. Inspecciona o muta
1004
+ * la configuración del logger en vivo desde la DevTools console.
1005
+ *
1006
+ * Acepta tres modos de invocación:
1007
+ * - Sin argumentos: vuelca el estado actual como tabla agrupada.
1008
+ * - JSON completo (empieza con `{`): aplica un objeto de configuración parcial.
1009
+ * - Pares `key=value` separados por coma: atajo para mutaciones puntuales.
1010
+ *
1011
+ * Solo se aplican las keys de la whitelist interna (`theme`, `verbosity`,
1012
+ * `enableColors`, `enableTimestamps`, `enableStackTrace`, `globalPrefix`,
1013
+ * `bannerType`); cualquier otra key se rechaza con un `warn` y se ignora.
1014
+ *
1015
+ * @example
1016
+ * // Sin argumentos: ver estado actual
1017
+ * // > /config
1018
+ *
1019
+ * @example
1020
+ * // Objeto JSON completo
1021
+ * // > /config {"theme":"neon","verbosity":"debug"}
1022
+ *
1023
+ * @example
1024
+ * // Atajo key=value (múltiples pares separados por coma)
1025
+ * // > /config theme=neon,verbosity=debug,globalPrefix=MiApp
1026
+ *
1027
+ * @see {@link ICommand} para el contrato que implementa este comando.
1028
+ * @see {@link Logger.setTheme}, {@link Logger.setVerbosity},
1029
+ * {@link Logger.setBannerType}, {@link Logger.setGlobalPrefix}
1030
+ * para los setters subyacentes.
377
1031
  */
378
1032
  var ConfigCommand = class {
379
1033
  name = "config";
380
1034
  description = "Show or update logger configuration";
381
1035
  usage = "/config [json|key=value,...]";
1036
+ /**
1037
+ * Ejecuta el comando `/config` contra el logger dado.
1038
+ *
1039
+ * @param args - Argumentos crudos del usuario. Vacío = status; con `{`
1040
+ * inicial = parse JSON; resto = pares `key=value` separados
1041
+ * por coma.
1042
+ * @param logger - Instancia destino cuyos setters se invocan.
1043
+ */
382
1044
  execute(args, logger) {
383
1045
  if (!args) {
384
1046
  this.showStatus(logger);
@@ -452,12 +1114,30 @@ var ConfigCommand = class {
452
1114
  //#endregion
453
1115
  //#region src/cli/commands/ThemeCommand.ts
454
1116
  /**
455
- * Themes command - show available themes
1117
+ * Comando `/themes` del CLI runtime del {@link Logger}. Lista los presets
1118
+ * temáticos disponibles en {@link THEME_PRESETS}, renderizando una preview
1119
+ * con los colores reales de cada tema (background, foreground, border).
1120
+ *
1121
+ * Es de solo lectura: no muta el logger. Útil para descubrir qué tema
1122
+ * aplicar antes de correr `/config theme=<name>`.
1123
+ *
1124
+ * @example
1125
+ * // Listar todos los temas con preview coloreada
1126
+ * // > /themes
1127
+ *
1128
+ * @see {@link THEME_PRESETS} para el catálogo completo de temas.
1129
+ * @see {@link ConfigCommand} para aplicar un tema vía `/config theme=...`.
456
1130
  */
457
1131
  var ThemesCommand = class {
458
1132
  name = "themes";
459
1133
  description = "Show available theme presets";
460
1134
  usage = "/themes";
1135
+ /**
1136
+ * Ejecuta el comando `/themes` contra el logger dado.
1137
+ *
1138
+ * @param _args - Ignorado (comando sin parámetros).
1139
+ * @param logger - Instancia usada para abrir/cerrar el `group` de salida.
1140
+ */
461
1141
  execute(_args, logger) {
462
1142
  logger.group("🎨 Available Themes");
463
1143
  Object.keys(require_styling.THEME_PRESETS).forEach((themeName) => {
@@ -469,12 +1149,30 @@ var ThemesCommand = class {
469
1149
  }
470
1150
  };
471
1151
  /**
472
- * Banners command - show available banner types
1152
+ * Comando `/banners` del CLI runtime del {@link Logger}. Enumera los tipos
1153
+ * de banner disponibles en {@link BANNER_VARIANTS} (`simple`, `ascii`,
1154
+ * `unicode`, ...) con una mini-preview de cada uno para inspección visual.
1155
+ *
1156
+ * Es de solo lectura: no muta el logger. Para cambiar el banner activo
1157
+ * usar {@link BannerCommand}.
1158
+ *
1159
+ * @example
1160
+ * // Listar todas las variantes de banner con preview
1161
+ * // > /banners
1162
+ *
1163
+ * @see {@link BANNER_VARIANTS} para el catálogo completo de variantes.
1164
+ * @see {@link BannerCommand} para aplicar un tipo concreto.
473
1165
  */
474
1166
  var BannersCommand = class {
475
1167
  name = "banners";
476
1168
  description = "Show available banner types";
477
1169
  usage = "/banners";
1170
+ /**
1171
+ * Ejecuta el comando `/banners` contra el logger dado.
1172
+ *
1173
+ * @param _args - Ignorado (comando sin parámetros).
1174
+ * @param logger - Instancia usada para abrir/cerrar el `group` de salida.
1175
+ */
478
1176
  execute(_args, logger) {
479
1177
  logger.group("🖼️ Available Banner Types");
480
1178
  Object.keys(require_styling.BANNER_VARIANTS).forEach((bannerName) => {
@@ -490,12 +1188,35 @@ var BannersCommand = class {
490
1188
  }
491
1189
  };
492
1190
  /**
493
- * Banner command - change/show banner type
1191
+ * Comando `/banner [type]` del CLI runtime del {@link Logger}.
1192
+ *
1193
+ * - Sin argumentos: re-renderiza el banner actualmente activo.
1194
+ * - Con un tipo válido: lo aplica vía {@link Logger.setBannerType} y lo
1195
+ * muestra inmediatamente.
1196
+ * - Con un tipo inválido: loguea un `error` listando las opciones válidas.
1197
+ *
1198
+ * @example
1199
+ * // Mostrar el banner actual
1200
+ * // > /banner
1201
+ *
1202
+ * @example
1203
+ * // Cambiar a un tipo concreto
1204
+ * // > /banner ascii
1205
+ *
1206
+ * @see {@link BANNER_VARIANTS} para los tipos aceptados.
1207
+ * @see {@link Logger.setBannerType} y {@link Logger.showBanner} para los
1208
+ * métodos subyacentes.
494
1209
  */
495
1210
  var BannerCommand = class {
496
1211
  name = "banner";
497
1212
  description = "Change or show current banner type";
498
1213
  usage = "/banner [type]";
1214
+ /**
1215
+ * Ejecuta el comando `/banner` contra el logger dado.
1216
+ *
1217
+ * @param args - Tipo de banner solicitado. Vacío = mostrar banner actual.
1218
+ * @param logger - Instancia destino cuyo banner se actualiza/muestra.
1219
+ */
499
1220
  execute(args, logger) {
500
1221
  if (!args) {
501
1222
  logger.showBanner();
@@ -510,12 +1231,27 @@ var BannerCommand = class {
510
1231
  //#endregion
511
1232
  //#region src/cli/commands/ExportCommand.ts
512
1233
  /**
513
- * Status command - show logger configuration and statistics
1234
+ * Comando `/status` del CLI runtime del {@link Logger}. Vuelca la
1235
+ * configuración vigente y algunas estadísticas (theme, verbosity, flags
1236
+ * de features, handler count, bufferSize) en una tabla agrupada dentro
1237
+ * de la consola. Es de solo lectura: no muta el logger.
1238
+ *
1239
+ * @example
1240
+ * // Inspeccionar el estado actual del logger
1241
+ * // > /status
1242
+ *
1243
+ * @see {@link Logger.getConfig} fuente de los datos mostrados.
514
1244
  */
515
1245
  var StatusCommand = class {
516
1246
  name = "status";
517
1247
  description = "Show current logger status and configuration";
518
1248
  usage = "/status";
1249
+ /**
1250
+ * Ejecuta el comando `/status` contra el logger dado.
1251
+ *
1252
+ * @param _args - Ignorado (comando sin parámetros).
1253
+ * @param logger - Instancia de la que se lee la configuración.
1254
+ */
519
1255
  execute(_args, logger) {
520
1256
  const config = logger.getConfig();
521
1257
  const statusData = {
@@ -535,23 +1271,54 @@ var StatusCommand = class {
535
1271
  }
536
1272
  };
537
1273
  /**
538
- * Reset command - reset logger to defaults
1274
+ * Comando `/reset` del CLI runtime del {@link Logger}. Restaura la
1275
+ * configuración a sus defaults de fábrica vía {@link Logger.resetConfig}.
1276
+ * No resetea handlers ni transports registrados — solo config.
1277
+ *
1278
+ * @example
1279
+ * // Volver a la configuración por defecto
1280
+ * // > /reset
1281
+ *
1282
+ * @see {@link Logger.resetConfig} para el método subyacente.
539
1283
  */
540
1284
  var ResetCommand = class {
541
1285
  name = "reset";
542
1286
  description = "Reset logger configuration to defaults";
543
1287
  usage = "/reset";
1288
+ /**
1289
+ * Ejecuta el comando `/reset` contra el logger dado.
1290
+ *
1291
+ * @param _args - Ignorado (comando sin parámetros).
1292
+ * @param logger - Instancia cuya configuración se resetea.
1293
+ */
544
1294
  execute(_args, logger) {
545
1295
  logger.resetConfig();
546
1296
  }
547
1297
  };
548
1298
  /**
549
- * Demo command - show logger feature demonstration
1299
+ * Comando `/demo` del CLI runtime del {@link Logger}. Ejecuta una
1300
+ * demostración integral de las capacidades del logger: todos los niveles
1301
+ * de log (debug → critical), tablas, timers (`time`/`timeEnd`), SVG inline
1302
+ * y mensajes animados. Útil para validar que el styling funciona en un
1303
+ * entorno nuevo o tras un cambio de tema.
1304
+ *
1305
+ * @example
1306
+ * // Lanzar la demo completa
1307
+ * // > /demo
1308
+ *
1309
+ * @see {@link Logger} para cada feature individual (`table`, `time`,
1310
+ * `logWithSVG`, `logAnimated`, ...).
550
1311
  */
551
1312
  var DemoCommand = class {
552
1313
  name = "demo";
553
1314
  description = "Show comprehensive feature demonstration";
554
1315
  usage = "/demo";
1316
+ /**
1317
+ * Ejecuta el comando `/demo` contra el logger dado.
1318
+ *
1319
+ * @param _args - Ignorado (comando sin parámetros).
1320
+ * @param logger - Instancia sobre la que se ejecutan los ejemplos.
1321
+ */
555
1322
  execute(_args, logger) {
556
1323
  logger.group("🎪 Advanced Logger Demo");
557
1324
  logger.debug("Debug message with detailed information");
@@ -597,12 +1364,38 @@ var DemoCommand = class {
597
1364
  //#endregion
598
1365
  //#region src/cli/help.ts
599
1366
  /**
600
- * Help command - show comprehensive CLI help
1367
+ * Comando `/help`: renderiza en consola el panel de ayuda del CLI con todos
1368
+ * los comandos disponibles, opciones de configuración, filtros de export y
1369
+ * ejemplos. El panel usa un gradient claro con {@link StyleBuilder} y los
1370
+ * quick tips se agrupan vía `logger.group`.
1371
+ *
1372
+ * Registrado por defecto por {@link createDefaultCLI}.
1373
+ *
1374
+ * @example
1375
+ * ```ts
1376
+ * const cli = createDefaultCLI();
1377
+ * await cli.processCommand('/help', logger);
1378
+ * // Imprime el panel ASCII con gradient + grupo "Quick Tips".
1379
+ * ```
1380
+ *
1381
+ * @see {@link ICommand}
1382
+ * @see {@link createDefaultCLI}
601
1383
  */
602
1384
  var HelpCommand = class {
603
1385
  name = "help";
604
1386
  description = "Show CLI help and available commands";
605
1387
  usage = "/help [command]";
1388
+ /**
1389
+ * Renderiza el panel de ayuda completo. Actualmente ignora `_args`: el
1390
+ * `usage` declara `/help [command]` (sub-comando opcional) pero la
1391
+ * implementación siempre muestra el panel global.
1392
+ *
1393
+ * @param {string} _args - Argumentos opcionales (reservado para ayuda por
1394
+ * sub-comando; sin uso actual).
1395
+ * @param {Logger} logger - Logger activo; se usa solo para `group`/`info`
1396
+ * de los quick tips.
1397
+ * @returns {void}
1398
+ */
606
1399
  execute(_args, logger) {
607
1400
  const helpStyle = new require_styling.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();
608
1401
  console.log(`%c
@@ -702,7 +1495,30 @@ var HelpCommand = class {
702
1495
  //#endregion
703
1496
  //#region src/cli/index.ts
704
1497
  /**
705
- * Create and configure default CLI processor
1498
+ * Crea un {@link CommandProcessor} con los 8 comandos estándar ya registrados:
1499
+ * `help`, `config`, `themes`, `banners`, `banner`, `status`, `reset` y
1500
+ * `demo`. Es el factory canónico — los consumidores normalmente no construyen
1501
+ * un `CommandProcessor` vacío a mano, ya que este no trae comandos cargados.
1502
+ *
1503
+ * @returns {CommandProcessor} Processor listo para usar, sin modo interactivo activo.
1504
+ *
1505
+ * @example
1506
+ * ```ts
1507
+ * const cli = createDefaultCLI();
1508
+ * await cli.processCommand('/help', logger);
1509
+ * await cli.processCommand('/config theme=neon', logger);
1510
+ * ```
1511
+ *
1512
+ * @example
1513
+ * ```ts
1514
+ * // Modo interactivo en el navegador: expone `window.cli`
1515
+ * const cli = createDefaultCLI();
1516
+ * cli.enterInteractiveMode(logger);
1517
+ * // desde devtools: cli('themes') → procesa '/themes'
1518
+ * ```
1519
+ *
1520
+ * @see {@link CommandProcessor}
1521
+ * @see {@link HelpCommand}
706
1522
  */
707
1523
  function createDefaultCLI() {
708
1524
  const processor = new CommandProcessor();
@@ -719,7 +1535,9 @@ function createDefaultCLI() {
719
1535
  //#endregion
720
1536
  //#region src/transports/TransportBridge.ts
721
1537
  /**
722
- * Creates a TransportBridge instance.
1538
+ * Crea una instancia de {@link TransportBridge}.
1539
+ *
1540
+ * @internal
723
1541
  */
724
1542
  function createTransportBridge() {
725
1543
  let transportManager;
@@ -747,9 +1565,170 @@ function createTransportBridge() {
747
1565
  };
748
1566
  }
749
1567
  //#endregion
1568
+ //#region src/transports/SpanRuntime.ts
1569
+ /** ALS singleton del módulo — compartido por todas las instancias de Logger.
1570
+ *
1571
+ * Resolución por capas (global → `process.getBuiltinModule` → `require`,
1572
+ * undefined en browser) delegada al helper compartido
1573
+ * {@link resolveAsyncLocalStorage} — ver su doc para el detalle de capas.
1574
+ * `context/LogContext.ts` usa el mismo helper para su ALS de MDC. */
1575
+ const activeSpanStore = require_LogContext.resolveAsyncLocalStorage();
1576
+ /**
1577
+ * Span activo en el call stack corriente (dentro de `span(fn)`), si lo hay.
1578
+ * Lo consumen la correlación log→span (`TransportRecord.traceId/spanId`) y la
1579
+ * resolución de `parentSpanId` en spans hijos.
1580
+ */
1581
+ function getActiveSpan() {
1582
+ return activeSpanStore?.getStore();
1583
+ }
1584
+ /**
1585
+ * Ejecuta `fn` con `record` como span activo. Sin ALS disponible (browser),
1586
+ * ejecuta `fn` directamente — sin correlación pero funcional.
1587
+ */
1588
+ function runWithActiveSpan(record, fn) {
1589
+ return activeSpanStore ? activeSpanStore.run(record, fn) : fn();
1590
+ }
1591
+ /** Nanosegundos Unix actuales como string decimal (formato OTLP). */
1592
+ function nowUnixNano() {
1593
+ return String(BigInt(Date.now()) * 1000000n);
1594
+ }
1595
+ /**
1596
+ * Hex aleatorio de `bytes` bytes. Usa `crypto.getRandomValues`; sin
1597
+ * `crypto` (runtimes exóticos) degrada a `Math.random` — suficiente para ids
1598
+ * de correlación, no para secrets.
1599
+ */
1600
+ function randomHex(bytes) {
1601
+ const cryptoObj = globalThis.crypto;
1602
+ if (cryptoObj?.getRandomValues) {
1603
+ const buf = new Uint8Array(bytes);
1604
+ cryptoObj.getRandomValues(buf);
1605
+ let out = "";
1606
+ for (const b of buf) out += b.toString(16).padStart(2, "0");
1607
+ return out;
1608
+ }
1609
+ let out = "";
1610
+ for (let i = 0; i < bytes * 2; i++) out += Math.floor(Math.random() * 16).toString(16);
1611
+ return out;
1612
+ }
1613
+ /** Trace id W3C: 16 bytes → 32 chars hex. */
1614
+ function generateTraceId() {
1615
+ return randomHex(16);
1616
+ }
1617
+ /** Span id W3C: 8 bytes → 16 chars hex. */
1618
+ function generateSpanId() {
1619
+ return randomHex(8);
1620
+ }
1621
+ /**
1622
+ * Registry de spans abiertos (leak-safety). Cubre tanto los de `startSpan()`
1623
+ * (externally-ended, el caso del handoff) como los de `span(fn)` en curso:
1624
+ * si un flush llega mid-flight, es mejor exportar el span incompleto que
1625
+ * tirarlo. El doble-`end()` es no-op, así que el cierre natural posterior no
1626
+ * duplica el export.
1627
+ */
1628
+ const openSpans = /* @__PURE__ */ new Map();
1629
+ /**
1630
+ * Crea el record de span y su {@link Span} handle. El handle registra el
1631
+ * span en el registry de abiertos; `onEnd` se invoca una única vez, con el
1632
+ * record final (duración real o `incomplete: true`), para su export al
1633
+ * pipeline de transports.
1634
+ *
1635
+ * `end()` solo fija `endTimeUnixNano` si no se fijó antes — así los
1636
+ * point-spans (`event()`) pueden fijar `end = start` exacto.
1637
+ *
1638
+ * @param name - Nombre de la operación.
1639
+ * @param attributes - Attributes iniciales (copia propia del record).
1640
+ * @param scope - Scope del logger emisor.
1641
+ * @param onEnd - Callback de export; recibe el record cerrado.
1642
+ * @returns El record (para el ALS store) y el handle del span.
1643
+ */
1644
+ function createSpan(name, attributes, scope, onEnd) {
1645
+ const parent = getActiveSpan();
1646
+ const record = {
1647
+ kind: "span",
1648
+ traceId: parent?.traceId ?? generateTraceId(),
1649
+ spanId: generateSpanId(),
1650
+ parentSpanId: parent?.spanId,
1651
+ name,
1652
+ spanKind: 1,
1653
+ startTimeUnixNano: nowUnixNano(),
1654
+ endTimeUnixNano: "0",
1655
+ attributes: { ...attributes ?? {} },
1656
+ scope
1657
+ };
1658
+ let ended = false;
1659
+ const finish = () => {
1660
+ if (ended) return;
1661
+ ended = true;
1662
+ openSpans.delete(record);
1663
+ onEnd(record);
1664
+ };
1665
+ openSpans.set(record, {
1666
+ record,
1667
+ end: finish,
1668
+ forceEnd: () => {
1669
+ if (ended) return;
1670
+ record.incomplete = true;
1671
+ if (record.endTimeUnixNano === "0") record.endTimeUnixNano = nowUnixNano();
1672
+ finish();
1673
+ }
1674
+ });
1675
+ const handle = {
1676
+ traceId: record.traceId,
1677
+ spanId: record.spanId,
1678
+ set(key, value) {
1679
+ record.attributes[key] = value;
1680
+ return handle;
1681
+ },
1682
+ end(attributes) {
1683
+ if (attributes) Object.assign(record.attributes, attributes);
1684
+ if (ended) return;
1685
+ if (record.endTimeUnixNano === "0") record.endTimeUnixNano = nowUnixNano();
1686
+ finish();
1687
+ },
1688
+ fail(err) {
1689
+ if (ended) return;
1690
+ record.status = {
1691
+ code: 2,
1692
+ message: err instanceof Error ? err.message : String(err)
1693
+ };
1694
+ this.end();
1695
+ }
1696
+ };
1697
+ return {
1698
+ record,
1699
+ span: handle
1700
+ };
1701
+ }
1702
+ /**
1703
+ * Emite un point-span (`event()`): start = end exactamente, sin registro en
1704
+ * abiertos tras el cierre — no hay leak posible. El `parentSpanId` se resuelve
1705
+ * contra el span activo si existe, pero NO fija contexto ALS.
1706
+ */
1707
+ function emitEventSpan(name, attributes, scope, onEnd) {
1708
+ const { record, span } = createSpan(name, attributes, scope, onEnd);
1709
+ record.endTimeUnixNano = record.startTimeUnixNano;
1710
+ span.end();
1711
+ }
1712
+ /**
1713
+ * Fuerza el cierre de todos los spans abiertos (`incomplete: true`) y los
1714
+ * exporta vía el `onEnd` de cada uno. Lo invocan `flushTransports()` /
1715
+ * `closeTransports()` / `cleanup()` ANTES del flush real — un span abierto
1716
+ * nunca se tira en shutdown.
1717
+ *
1718
+ * @returns Los records forzados a cerrar (para diagnóstico/tests).
1719
+ */
1720
+ function forceCloseOpenSpans() {
1721
+ const snapshot = [...openSpans.values()];
1722
+ for (const entry of snapshot) entry.forceEnd();
1723
+ return snapshot.map((entry) => entry.record);
1724
+ }
1725
+ //#endregion
750
1726
  //#region src/playground/TerminalBridge.ts
751
1727
  /**
752
- * Creates a TerminalBridge using a getter to avoid circular reference at construction.
1728
+ * Crea un {@link TerminalBridge} usando un getter para evitar referencias
1729
+ * circulares en la construcción.
1730
+ *
1731
+ * @internal
753
1732
  */
754
1733
  function createTerminalBridge(options) {
755
1734
  let _showPrimitives = true;
@@ -874,37 +1853,38 @@ var Logger = class Logger {
874
1853
  hookBridge;
875
1854
  logContext;
876
1855
  transportBridge;
877
- /** Set during success() so log() skips its own dispatch (N2 fix). */
1856
+ /** Fijado por `success()` para que `log()` salte su propio dispatch. */
878
1857
  _successTagDispatched = false;
879
1858
  styleManager;
880
- /** Whether CLI primitives (step, box, header, etc.) should be shown*/
1859
+ /** Controla si las CLI primitives (step, box, header, ...) deben renderizarse. */
881
1860
  _showPrimitives = true;
882
1861
  terminalBridge;
883
1862
  /**
884
- * Active smart-preset reference (set by `preset()`). Typed as `unknown`
885
- * to keep the public surface clean; consumed by `createStyledOutput`.
1863
+ * Referencia activa al smart-preset (fijada por `preset()`). Tipada como
1864
+ * `unknown` para mantener limpia la surface pública; la consume
1865
+ * `createStyledOutput`.
886
1866
  */
887
1867
  _activePreset;
888
1868
  /**
889
- * Name of the active smart-preset. Stored separately so theme-change
890
- * detection can re-render without re-running the preset body.
1869
+ * Nombre del smart-preset activo. Se guarda aparte para que la detección
1870
+ * de cambio de tema pueda re-renderizar sin re-ejecutar el body del preset.
891
1871
  */
892
1872
  _activePresetName;
893
1873
  /**
894
- * Last-applied `customize()` overrides. Stored for later read by
895
- * `createStyledOutput`.
1874
+ * Overrides aplicados por el último `customize()`. Se conservan para que
1875
+ * `createStyledOutput` los lea después.
896
1876
  */
897
1877
  _customization;
898
1878
  /**
899
- * This logger's own context bindings (from child() calls).
900
- * Single source of truth for this logger's contribution to the context chain.
1879
+ * Bindings propios de este logger (provenientes de llamadas a `child()`).
1880
+ * Source of truth única de la contribución de este logger a la cadena de contexto.
901
1881
  * @private
902
1882
  */
903
1883
  _bindings = {};
904
1884
  /**
905
- * Reference to the parent's merged context record at the time this logger
906
- * was created. Together with _bindings, forms the context chain.
907
- * Undefined for the root logger.
1885
+ * Referencia al record de contexto mergueado del parent en el momento en
1886
+ * que se creó este logger. Junto con `_bindings`, forma la cadena de
1887
+ * contexto. `undefined` para el logger raíz.
908
1888
  * @private
909
1889
  */
910
1890
  _parentContextRecord;
@@ -1072,65 +2052,66 @@ var Logger = class Logger {
1072
2052
  this.success(`Banner type changed to: ${bannerType}`);
1073
2053
  }
1074
2054
  /**
1075
- * Runs `fn` within an AsyncLocalStorage scope where `bindings` are
1076
- * merged into the context for all log calls inside `fn`.
2055
+ * Ejecuta `fn` dentro de un scope AsyncLocalStorage donde `bindings` se
2056
+ * merguean al contexto para todas las llamadas de log dentro de `fn`.
1077
2057
  *
1078
- * Without `fn` (the old setter shape): no-op for backwards compatibility.
1079
- * Prefer `child()` for persistent bindings or `withContextAsync()` for
1080
- * async callbacks.
2058
+ * Sin `fn` (el shape legacy de setter): no-op por backwards compatibility.
2059
+ * Preferir `child()` para bindings persistentes o `withContextAsync()`
2060
+ * para callbacks async.
1081
2061
  *
1082
- * @param bindings - Key-value pairs to attach for the duration of `fn`
1083
- * @param fn - Optional synchronous function to run with scoped bindings
1084
- * @returns The return value of `fn`, or undefined if no fn provided
2062
+ * @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
2063
+ * @param fn - Función sincrónica opcional a ejecutar con los bindings en scope
2064
+ * @returns El valor de retorno de `fn`, o `undefined` si no se pasa `fn`
1085
2065
  *
1086
2066
  * @example
1087
- * // Scoped synchronous callback
2067
+ * // Callback sincrónico scoped
1088
2068
  * logger.withContext({ requestId: 'r-42' }, () => {
1089
- * doWork(); // logs inside see requestId in attributes
2069
+ * doWork(); // los logs de aquí ven requestId en attributes
1090
2070
  * });
1091
2071
  *
1092
2072
  * @example
1093
- * // Persistent binding: use child()
2073
+ * // Binding persistente: usar child()
1094
2074
  * const reqLog = logger.child({ requestId: 'r-42' });
1095
- * reqLog.info('handling request'); // attributes include requestId
2075
+ * reqLog.info('handling request'); // attributes incluye requestId
1096
2076
  *
1097
- * @see {@link child} for an immutable copy with the merged context
1098
- * @see {@link withContextAsync} for async callback variant
2077
+ * @see {@link child} para una copia inmutable con el contexto mergueado
2078
+ * @see {@link withContextAsync} para la variante con callback async
1099
2079
  */
1100
2080
  withContext(bindings, fn) {
1101
2081
  return this.logContext.withContext(bindings, fn);
1102
2082
  }
1103
2083
  /**
1104
- * Async variant of `withContext`. Runs `fn` within an AsyncLocalStorage
1105
- * scope so bindings are available to all async log calls inside `fn`.
2084
+ * Variante async de `withContext`. Ejecuta `fn` dentro de un scope
2085
+ * AsyncLocalStorage para que los bindings estén disponibles a todas las
2086
+ * llamadas de log async dentro de `fn`.
1106
2087
  *
1107
- * @param bindings - Key-value pairs to attach for the duration of `fn`
1108
- * @param fn - Async function to run with the scoped bindings
1109
- * @returns The return value of `fn`
2088
+ * @param bindings - Pares key-value a adjuntar durante la ejecución de `fn`
2089
+ * @param fn - Función async a ejecutar con los bindings en scope
2090
+ * @returns El valor de retorno de `fn`
1110
2091
  *
1111
2092
  * @example
1112
2093
  * await logger.withContextAsync({ requestId: 'r-42' }, async () => {
1113
- * await fetchData(); // logs inside see requestId in attributes
2094
+ * await fetchData(); // los logs de aquí ven requestId en attributes
1114
2095
  * });
1115
2096
  *
1116
- * @see {@link child} for a persistent child logger
1117
- * @see {@link withContext} for synchronous callback variant
2097
+ * @see {@link child} para un child logger persistente
2098
+ * @see {@link withContext} para la variante con callback sincrónico
1118
2099
  */
1119
2100
  withContextAsync(bindings, fn) {
1120
2101
  return this.logContext.withContextAsync(bindings, fn);
1121
2102
  }
1122
2103
  /**
1123
- * Returns an immutable copy of this logger with the extra context bound.
1124
- * Future calls on the child emit with the merged context, without
1125
- * mutating the parent — the canonical MDC pattern.
2104
+ * Devuelve una copia inmutable de este logger con el contexto extra bound.
2105
+ * Las llamadas futuras sobre el child emiten con el contexto mergueado,
2106
+ * sin mutar al parent — el patrón canónico de MDC.
1126
2107
  *
1127
- * @param extra - Key-value pairs to attach (requestId, userId, ...)
1128
- * @returns A new Logger with merged context
2108
+ * @param extra - Pares key-value a adjuntar (requestId, userId, ...)
2109
+ * @returns Un nuevo Logger con el contexto mergueado
1129
2110
  *
1130
2111
  * @example
1131
2112
  * const reqLog = logger.child({ requestId: req.id });
1132
- * reqLog.info('start'); // emits attributes: { requestId }
1133
- * logger.info('unrelated'); // NOT affected — parent's context untouched
2113
+ * reqLog.info('start'); // emite attributes: { requestId }
2114
+ * logger.info('unrelated'); // NO afectado — el contexto del parent queda intacto
1134
2115
  *
1135
2116
  */
1136
2117
  child(extra) {
@@ -1140,21 +2121,21 @@ var Logger = class Logger {
1140
2121
  return childLogger;
1141
2122
  }
1142
2123
  /**
1143
- * Drops every key from the bound context. After this call, emitted
1144
- * records no longer carry `attributes` until {@link withContext} or
1145
- * {@link child} re-establish one.
2124
+ * Descarta todas las keys del contexto bound. Tras esta llamada, los
2125
+ * records emitidos dejan de llevar `attributes` hasta que
2126
+ * {@link withContext} o {@link child} restablezcan uno.
1146
2127
  *
1147
- * @returns The same logger instance, now context-free
2128
+ * @returns La misma instancia del logger, ahora sin contexto
1148
2129
  */
1149
2130
  clearContext() {
1150
2131
  this.logContext.clearContext();
1151
2132
  return this;
1152
2133
  }
1153
2134
  /**
1154
- * Snapshot of the bound context. Returned object is a shallow copy:
1155
- * mutating it does NOT affect what subsequent log calls emit.
2135
+ * Snapshot del contexto bound. El objeto devuelto es una shallow copy:
2136
+ * mutarlo NO afecta lo que emiten las llamadas de log posteriores.
1156
2137
  *
1157
- * @returns A read-only snapshot of the current context
2138
+ * @returns Un snapshot read-only del contexto actual
1158
2139
  */
1159
2140
  getContext() {
1160
2141
  let merged = this._parentContextRecord ?? {};
@@ -1165,12 +2146,12 @@ var Logger = class Logger {
1165
2146
  return merged;
1166
2147
  }
1167
2148
  /**
1168
- * Updates the default OTel resource (service.name, version, env).
1169
- * Persisted into every emitted record's `resource` field unless the
1170
- * record itself overrides it.
2149
+ * Actualiza el resource OTel por defecto (service.name, version, env).
2150
+ * Se persiste en el campo `resource` de cada record emitido, salvo que
2151
+ * el propio record lo override.
1171
2152
  *
1172
- * @param resource - Partial OTel resource to merge into the current one
1173
- * @returns The same logger instance, for chaining
2153
+ * @param resource - Resource OTel parcial a merguear con el actual
2154
+ * @returns La misma instancia del logger, para chaining
1174
2155
  *
1175
2156
  * @example
1176
2157
  * logger.setResource({ 'service.name': 'api', 'service.version': '1.2.3' });
@@ -1199,20 +2180,15 @@ var Logger = class Logger {
1199
2180
  this.success("Logger configuration reset to defaults");
1200
2181
  }
1201
2182
  /**
1202
- * Método de limpieza para eliminar listeners y liberar recursos
1203
- *
1204
- * @example
1205
- * // Antes de cerrar la aplicación
1206
- * logger.cleanup();
1207
- *
1208
- */
1209
- /**
1210
- * Tears down every resource held by this Logger. Safe to call multiple
1211
- * times. Fixed in 5.1.0 to fully drain transports + clear timers +
1212
- * drop the legacy handler list + reset group depth + clear context.
2183
+ * Método de limpieza para eliminar listeners y liberar recursos.
2184
+ *
2185
+ * Vacía los transports (drain), limpia timers, suelta la lista de
2186
+ * handlers legacy, resetea el group depth y limpia el context.
2187
+ * Seguro de invocar múltiples veces.
1213
2188
  *
1214
2189
  * @example
1215
- * await logger.cleanup(); // before process exit / hot reload
2190
+ * // Antes de cerrar la aplicación
2191
+ * await logger.cleanup();
1216
2192
  *
1217
2193
  */
1218
2194
  async cleanup() {
@@ -1222,6 +2198,7 @@ var Logger = class Logger {
1222
2198
  } catch {}
1223
2199
  this.themeChangeListener = null;
1224
2200
  }
2201
+ forceCloseOpenSpans();
1225
2202
  await this.transportBridge.closeTransports();
1226
2203
  this.handlers.length = 0;
1227
2204
  this.timers.clear();
@@ -1241,7 +2218,7 @@ var Logger = class Logger {
1241
2218
  * logger.preset('glassmorphism'); // Efectos de blur modernos
1242
2219
  * logger.preset('minimal'); // Minimalista y elegante
1243
2220
  * logger.preset('debug'); // Modo desarrollo detallado
1244
- * logger.preset('production'); // Optimizado para producción
2221
+ * logger.preset('production'); // Enfocado en producción
1245
2222
  *
1246
2223
  */
1247
2224
  preset(name) {
@@ -1387,12 +2364,63 @@ var Logger = class Logger {
1387
2364
  this.badgeList = [];
1388
2365
  return this;
1389
2366
  }
2367
+ /**
2368
+ * Crea un logger scoped para un componente o módulo del dominio.
2369
+ *
2370
+ * El `ComponentLogger` resultante prepends un badge `[name]` a cada
2371
+ * mensaje y comparte configuración, transports y hooks con el logger
2372
+ * padre. Útil para trazar el origen de los logs en apps con muchos
2373
+ * módulos (Auth, DB, Cache, ...).
2374
+ *
2375
+ * @param {string} name - Nombre del componente que aparecerá como badge
2376
+ * @returns {ComponentLogger} Logger scoped para el componente
2377
+ *
2378
+ * @example
2379
+ * const auth = logger.component('Auth');
2380
+ * auth.info('Validando token'); // [Auth] Validando token
2381
+ * auth.success('Token válido');
2382
+ *
2383
+ * @see {@link api} para loggers de endpoints REST/GraphQL
2384
+ * @see {@link scope} para un scope genérico sin badge de componente
2385
+ */
1390
2386
  component(name) {
1391
2387
  return new ComponentLogger(this, name);
1392
2388
  }
2389
+ /**
2390
+ * Crea un logger scoped para un endpoint o surface de API.
2391
+ *
2392
+ * Como `component()` pero con styling orientado a APIs (badge `[API]`
2393
+ * por defecto más el nombre del sub-scope). Útil para distinguir
2394
+ * tráfico REST vs GraphQL vs WebSocket en los logs.
2395
+ *
2396
+ * @param {string} name - Nombre de la API o surface (p.ej. `'REST'`, `'GraphQL'`)
2397
+ * @returns {APILogger} Logger scoped para la API
2398
+ *
2399
+ * @example
2400
+ * const rest = logger.api('REST');
2401
+ * rest.info('GET /users/42'); // [API] [REST] GET /users/42
2402
+ *
2403
+ * @see {@link component} para loggers de componentes de dominio
2404
+ */
1393
2405
  api(name) {
1394
2406
  return new APILogger(this, name);
1395
2407
  }
2408
+ /**
2409
+ * Crea un logger scoped genérico con un prefijo.
2410
+ *
2411
+ * Variante minimal de `component()` / `api()`: solo aplica un prefijo
2412
+ * de scope sin badges ni styling especial. Útil para sub-módulos que
2413
+ * no encajan en las categorías de `component`/`api`.
2414
+ *
2415
+ * @param {string} name - Texto del prefijo de scope
2416
+ * @returns {ScopedLogger} Logger con el scope aplicado
2417
+ *
2418
+ * @example
2419
+ * const db = logger.scope('db');
2420
+ * db.info('Pool conectado'); // [db] Pool conectado
2421
+ *
2422
+ * @see {@link component} y {@link api} para variantes con badges
2423
+ */
1396
2424
  scope(name) {
1397
2425
  return new ScopedLogger(this, name);
1398
2426
  }
@@ -1593,21 +2621,27 @@ var Logger = class Logger {
1593
2621
  return this.transportBridge.removeTransport(id);
1594
2622
  }
1595
2623
  /**
1596
- * Fuerza el flush de todos los transports
2624
+ * Fuerza el flush de todos los transports. Antes de flushear, cierra los
2625
+ * spans aún abiertos (`incomplete: true`) y los encola para export — un
2626
+ * span abierto nunca se tira en un flush.
1597
2627
  *
1598
2628
  * @returns Promise que resuelve cuando todos los buffers están vaciados
1599
2629
  *
1600
2630
  */
1601
2631
  async flushTransports() {
2632
+ forceCloseOpenSpans();
1602
2633
  await this.transportBridge.flushTransports();
1603
2634
  }
1604
2635
  /**
1605
- * Cierra todos los transports
2636
+ * Cierra todos los transports. Como en {@link flushTransports}, primero
2637
+ * fuerza el cierre de los spans abiertos para que viajen en el flush
2638
+ * final del close.
1606
2639
  *
1607
2640
  * @returns Promise que resuelve cuando todos están cerrados
1608
2641
  *
1609
2642
  */
1610
2643
  async closeTransports() {
2644
+ forceCloseOpenSpans();
1611
2645
  await this.transportBridge.closeTransports();
1612
2646
  }
1613
2647
  /**
@@ -1629,33 +2663,29 @@ var Logger = class Logger {
1629
2663
  return require_core.LOG_LEVELS[level] >= require_core.LOG_LEVELS[this.config.verbosity];
1630
2664
  }
1631
2665
  /**
1632
- * Builds and dispatches a `TransportRecord` to the {@link TransportManager}
1633
- * (no-op if no transports are registered). Shared by every log path —
1634
- * `log()`, `success()`, and visual methods like `table()` / `group()` /
1635
- * `time()` — so all emissions hit the same transport pipeline.
2666
+ * Tag pendiente de inyectar en el siguiente `TransportRecord` emitido
2667
+ * por `log()`. Lo fijan `success()` y `logWithBindingsAndTag()` antes
2668
+ * de delegar; `log()` lo consume y lo resetea a `undefined`.
1636
2669
  *
1637
- * @param level - The canonical log level (trace/debug/info/warn/error/critical)
1638
- * @param message - Final, post-hook message text
1639
- * @param prefix - Effective prefix (global + scope)
1640
- * @param stackInfo - Optional caller location
1641
- * @param extra - Optional fields to merge into the record (e.g. `{ tag: 'success' }`)
2670
+ * @internal
1642
2671
  */
1643
2672
  _dispatchTag;
1644
2673
  /**
1645
- * Computes the fully-merged context for this logger.
2674
+ * Computa el contexto completamente mergueado para este logger.
1646
2675
  *
1647
- * The context chain is built at child-creation time: each child stores
1648
- * its parent's fully-merged context (at that moment) as _parentContextRecord.
1649
- * This means _parentContextRecord already contains all ancestors' bindings
1650
- * in the correct precedence order (root first, nearest child last).
2676
+ * La cadena de contexto se construye en el momento de crear el child:
2677
+ * cada child almacena el contexto fully-merged de su parent (en ese
2678
+ * instante) como `_parentContextRecord`. Esto implica que
2679
+ * `_parentContextRecord` ya contiene los bindings de todos los ancestros
2680
+ * en el orden de precedencia correcto (root primero, child más cercano al final).
1651
2681
  *
1652
- * Merge order (later wins):
1653
- * 1. _parentContextRecord — parent's merged context snapshot at creation time
1654
- * 2. _bindings — this logger's own bindings (child() calls)
1655
- * 3. ALS store — withContext/withContextAsync scope (highest priority)
2682
+ * Orden de merge (gana el último):
2683
+ * 1. _parentContextRecord — snapshot del contexto mergueado del parent en la creación
2684
+ * 2. _bindings — bindings propios de este logger (llamadas a `child()`)
2685
+ * 3. ALS store — scope de `withContext`/`withContextAsync` (prioridad máxima)
1656
2686
  *
1657
2687
  * @internal
1658
- * @returns The merged context record
2688
+ * @returns El record de contexto mergueado
1659
2689
  */
1660
2690
  _getMergedContext() {
1661
2691
  let merged = this._parentContextRecord ?? {};
@@ -1670,7 +2700,7 @@ var Logger = class Logger {
1670
2700
  };
1671
2701
  return merged;
1672
2702
  }
1673
- /** @internal Exposes base merged context (no ALS) to LogContext child factory closure. */
2703
+ /** @internal Expone el contexto base mergueado (sin ALS) a la closure de la child factory de LogContext. */
1674
2704
  _captureMergedContext() {
1675
2705
  let merged = this._parentContextRecord ?? {};
1676
2706
  if (this._bindings && Object.keys(this._bindings).length > 0) merged = {
@@ -1679,6 +2709,21 @@ var Logger = class Logger {
1679
2709
  };
1680
2710
  return merged;
1681
2711
  }
2712
+ /**
2713
+ * Construye y despacha un `TransportRecord` al {@link TransportManager}
2714
+ * (no-op si no hay transports registrados). Lo comparten todos los
2715
+ * caminos de log — `log()`, `success()` y los métodos visuales como
2716
+ * `table()` / `group()` / `time()` — para que toda emisión atraviese
2717
+ * el mismo pipeline de transports.
2718
+ *
2719
+ * @protected
2720
+ * @param {LogLevel} level - Nivel canónico (trace/debug/info/warn/error/critical)
2721
+ * @param {string} message - Mensaje final, post-hook
2722
+ * @param {string | undefined} prefix - Prefijo efectivo (global + scope)
2723
+ * @param {StackInfo | null} stackInfo - Ubicación del caller, opcional
2724
+ * @param {Partial<TransportRecord>} [extra] - Campos extra a mergear en el record
2725
+ * (p.ej. `{ tag: 'success' }` o `attributes` adicionales)
2726
+ */
1682
2727
  dispatchToTransports(level, message, prefix, stackInfo, extra) {
1683
2728
  const record = {
1684
2729
  level,
@@ -1698,6 +2743,11 @@ var Logger = class Logger {
1698
2743
  resource: this.logContext._getResource() ? { ...this.logContext._getResource() } : void 0,
1699
2744
  ...extra
1700
2745
  };
2746
+ const activeSpan = getActiveSpan();
2747
+ if (activeSpan && !record.traceId) {
2748
+ record.traceId = activeSpan.traceId;
2749
+ record.spanId = activeSpan.spanId;
2750
+ }
1701
2751
  this.transportBridge.writeRecord(record);
1702
2752
  }
1703
2753
  /**
@@ -1710,37 +2760,23 @@ var Logger = class Logger {
1710
2760
  return parts.length > 0 ? parts.join(":") : void 0;
1711
2761
  }
1712
2762
  /**
1713
- * Método central de logging. Awaits the `beforeLog` hook pipeline
1714
- * synchronously (so redactions / enrichments are reflected in the
1715
- * emitted message before console + transport dispatch).
1716
- *
1717
- * Fire-and-forget callers (e.g. `logger.info(...)` without `await`)
1718
- * still work — the resulting `Promise<void>` is dropped on the floor.
1719
- * Awaiting is recommended when `beforeLog` hooks mutate `message`
1720
- * (e.g. PII redaction, correlation IDs).
1721
- *
1722
- * @protected
1723
- * @param level - Nivel del log
1724
- * @param args - Argumentos a loggear
1725
- * @returns Promise that resolves once the record has been dispatched
2763
+ * Método central de logging. Espera el hook pipeline `beforeLog`
2764
+ * antes de despachar a consola y transports, para que redacciones
2765
+ * o enriquecimientos (PII, correlation IDs) se reflejen en el
2766
+ * mensaje emitido.
1726
2767
  *
1727
- */
1728
- /**
1729
- * Protected logging method. Awaits the `beforeLog` hook pipeline
1730
- * synchronously (so redactions / enrichments are reflected in the
1731
- * emitted message before console + transport dispatch).
2768
+ * Los callers fire-and-forget (p.ej. `logger.info(...)` sin `await`)
2769
+ * siguen funcionando: el `Promise<void>` resultante se descarta.
2770
+ * Se recomienda `await` cuando los hooks `beforeLog` mutan `message`.
1732
2771
  *
1733
- * Fire-and-forget callers (e.g. `logger.info(...)` without `await`)
1734
- * still work — the resulting `Promise<void>` is dropped on the floor.
1735
- * Awaiting is recommended when `beforeLog` hooks mutate `message`
1736
- * (e.g. PII redaction, correlation IDs).
2772
+ * El tag opcional (`TransportRecord.tag`) NO se pasa como argumento:
2773
+ * se establece vía `_dispatchTag` (ver `success()` y
2774
+ * {@link logWithBindingsAndTag}) antes de invocar este método.
1737
2775
  *
1738
2776
  * @protected
1739
- * @param level - Nivel del log
1740
- * @param args - Argumentos a loggear
1741
- * @param tag - Optional tag forwarded to `dispatchToTransports` as
1742
- * `TransportRecord.tag` (e.g. `'success'` for success records).
1743
- * @returns Promise that resolves once the record has been dispatched
2777
+ * @param {LogLevel} level - Nivel del log
2778
+ * @param {unknown[]} args - Argumentos a loggear (mensaje + datos)
2779
+ * @returns {Promise<void>} Promesa que resuelve al completar el dispatch
1744
2780
  *
1745
2781
  */
1746
2782
  async log(level, ...args) {
@@ -1790,6 +2826,22 @@ var Logger = class Logger {
1790
2826
  else this.dispatchToTransports(level, message, prefix, stackInfo);
1791
2827
  this.hookBridge.getHookManager().emit("afterLog", processed).catch(() => {});
1792
2828
  }
2829
+ /**
2830
+ * Emite un log aplicando bindings (badges, scope) al prefijo del
2831
+ * mensaje antes de delegar en {@link Logger.log}.
2832
+ *
2833
+ * No es API pública de consumo: existe para que `ScopedLogger`
2834
+ * (`component()` / `api()` / `scope()`) pueda reutilizar el pipeline
2835
+ * central de `log()` sin duplicar la lógica de styling/badges.
2836
+ *
2837
+ * @internal
2838
+ * @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
2839
+ * @param {LogLevel} level - Nivel de log
2840
+ * @param {unknown[]} args - Argumentos a loggear
2841
+ * @returns {Promise<void>} Promesa del dispatch
2842
+ *
2843
+ * @see {@link logWithBindingsAndTag} para la variante con `tag`
2844
+ */
1793
2845
  logWithBindings(bindings, level, ...args) {
1794
2846
  if (!this.shouldLog(level)) return Promise.resolve();
1795
2847
  let prefix = "";
@@ -1800,19 +2852,45 @@ var Logger = class Logger {
1800
2852
  return this.log(level, ...args);
1801
2853
  }
1802
2854
  /**
1803
- * Like `logWithBindings()` but sets _dispatchTag first so that
1804
- * `log()` dispatches with the tag. Used by ScopedLogger.success()
1805
- * to propagate tag:'success' through the normal log() pipeline.
2855
+ * Como {@link logWithBindings} pero fija `_dispatchTag` antes de
2856
+ * delegar, para que `log()` despache el `TransportRecord` con el
2857
+ * tag indicado. Lo usa `ScopedLogger.success()` para propagar
2858
+ * `tag: 'success'` a través del pipeline normal de `log()`.
2859
+ *
2860
+ * @internal
2861
+ * @param {Bindings} bindings - Bindings de scope (badges, scope name, ...)
2862
+ * @param {LogLevel} level - Nivel de log
2863
+ * @param {LogTag} tag - Tag a inyectar en el `TransportRecord`
2864
+ * @param {unknown[]} args - Argumentos a loggear
2865
+ * @returns {Promise<void>} Promesa del dispatch
1806
2866
  */
1807
2867
  logWithBindingsAndTag(bindings, level, tag, ...args) {
1808
2868
  this._dispatchTag = tag;
1809
2869
  return this.logWithBindings(bindings, level, ...args);
1810
2870
  }
2871
+ /**
2872
+ * Registra mensajes de debug (nivel más verboso junto a `trace`).
2873
+ * Pensado para diagnóstico de desarrollo: valores intermedios, flags
2874
+ * de control flow, estado interno. Devuelve `Promise<void>`.
2875
+ *
2876
+ * Filtrado por defecto cuando `verbosity > 'debug'` (ver `setVerbosity`).
2877
+ *
2878
+ * @param {unknown[]} args - Mensaje + datos a inspeccionar
2879
+ * @returns {Promise<void>} Promesa del dispatch
2880
+ *
2881
+ * @example
2882
+ * logger.debug('Estado interno:', { conn, queueSize });
2883
+ * logger.debug('Entrando en branch X');
2884
+ *
2885
+ * @see {@link trace} para diagnósticos aún más granulares
2886
+ * @see {@link setVerbosity} para controlar el nivel mínimo visible
2887
+ */
1811
2888
  debug(...args) {
1812
2889
  return this.log("debug", ...args);
1813
2890
  }
1814
2891
  /**
1815
- * Registra mensajes informativos. Devuelve `Promise<void>` desde 5.1.0.
2892
+ * Registra mensajes informativos. El `await` retorna cuando el hook
2893
+ * `beforeLog` y el dispatch a transports han terminado.
1816
2894
  *
1817
2895
  * @param args - Mensajes y datos informativos
1818
2896
  *
@@ -1825,7 +2903,7 @@ var Logger = class Logger {
1825
2903
  return this.log("info", ...args);
1826
2904
  }
1827
2905
  /**
1828
- * Registra mensajes de advertencia. Devuelve `Promise<void>` desde 5.1.0.
2906
+ * Registra mensajes de advertencia.
1829
2907
  *
1830
2908
  * @param args - Mensajes de advertencia
1831
2909
  *
@@ -1834,7 +2912,7 @@ var Logger = class Logger {
1834
2912
  return this.log("warn", ...args);
1835
2913
  }
1836
2914
  /**
1837
- * Registra mensajes de error. Devuelve `Promise<void>` desde 5.1.0.
2915
+ * Registra mensajes de error.
1838
2916
  *
1839
2917
  * @param args - Mensaje de error y stack traces
1840
2918
  *
@@ -1914,7 +2992,7 @@ var Logger = class Logger {
1914
2992
  this.log("trace", ...args);
1915
2993
  }
1916
2994
  /**
1917
- * Registra errores críticos (prioridad más alta). Devuelve `Promise<void>` desde 5.1.0.
2995
+ * Registra errores críticos (prioridad más alta).
1918
2996
  *
1919
2997
  * @param args - Errores críticos del sistema
1920
2998
  *
@@ -1926,6 +3004,104 @@ var Logger = class Logger {
1926
3004
  return this.log("critical", ...args);
1927
3005
  }
1928
3006
  /**
3007
+ * Emite un **point-span**: un span con `start = end` para completion
3008
+ * signals y eventos puntuales (una operación instantánea, un hito).
3009
+ * No registra contexto activo ni puede leakear — se exporta de inmediato.
3010
+ *
3011
+ * El nombre `event` (y no `trace`) es deliberado: `trace` es un log level
3012
+ * (el -1) y está reservado.
3013
+ *
3014
+ * @param {string} name - Nombre del evento (`job.completed`, `cache.flushed`, ...).
3015
+ * @param {SpanAttributes} [attributes] - Attributes del span.
3016
+ *
3017
+ * @example
3018
+ * logger.event('build.finished', { status: 'ok', durationMs: 4200 });
3019
+ *
3020
+ * @see {@link span} para intervalos con work-block
3021
+ * @see {@link startSpan} para intervalos externally-ended
3022
+ */
3023
+ event(name, attributes) {
3024
+ emitEventSpan(name, attributes, this._spanScopeName(), (record) => {
3025
+ this.transportBridge.writeRecord(record);
3026
+ });
3027
+ }
3028
+ span(name, fnOrAttributes, maybeFn) {
3029
+ const { attributes, fn } = resolveSpanArgs(fnOrAttributes, maybeFn);
3030
+ return this._runSpan(name, attributes, this._spanScopeName(), fn);
3031
+ }
3032
+ /**
3033
+ * Inicia un span de intervalo **externally-ended**: devuelve el handle y
3034
+ * NO fija contexto ALS (el cierre ocurre fuera del bloque léxico — p.ej.
3035
+ * un `cli.spawn` que se cierra desde un poll o callback externo).
3036
+ *
3037
+ * Si el span no se cierra antes de `flushTransports()` / shutdown, el
3038
+ * flush lo fuerza a cerrar con `incomplete: true` y lo exporta — nunca
3039
+ * se tira.
3040
+ *
3041
+ * @param {string} name - Nombre de la operación.
3042
+ * @param {SpanAttributes} [attributes] - Attributes iniciales.
3043
+ * @returns {Span} Handle con `set`/`end`/`fail` y los ids del span.
3044
+ *
3045
+ * @example
3046
+ * const s = logger.startSpan('spawn.build', { cmd: 'make' });
3047
+ * proc.on('exit', code => {
3048
+ * if (code === 0) s.end({ exitCode: code });
3049
+ * else s.fail(new Error(`exit ${code}`));
3050
+ * });
3051
+ *
3052
+ * @see {@link span} para el caso con work-block
3053
+ */
3054
+ startSpan(name, attributes) {
3055
+ return this._startSpan(name, attributes, this._spanScopeName());
3056
+ }
3057
+ /**
3058
+ * Scope por defecto de los spans emitidos por este logger (el
3059
+ * `globalPrefix`, o `'root'`).
3060
+ * @internal
3061
+ */
3062
+ _spanScopeName() {
3063
+ return this.config.globalPrefix || "root";
3064
+ }
3065
+ /**
3066
+ * Emite un point-span con scope explícito. Lo consume
3067
+ * {@link ScopedLogger.event}, que pasa su scope compuesto.
3068
+ * @internal
3069
+ */
3070
+ _emitSpanEvent(name, attributes, scope) {
3071
+ emitEventSpan(name, attributes, scope, (record) => {
3072
+ this.transportBridge.writeRecord(record);
3073
+ });
3074
+ }
3075
+ /**
3076
+ * Crea un span externally-ended con scope explícito. Lo consume
3077
+ * {@link ScopedLogger.startSpan}.
3078
+ * @internal
3079
+ */
3080
+ _startSpan(name, attributes, scope) {
3081
+ const { span } = createSpan(name, attributes, scope, (record) => {
3082
+ this.transportBridge.writeRecord(record);
3083
+ });
3084
+ return span;
3085
+ }
3086
+ /**
3087
+ * Corre `fn` dentro de un span activo en el ALS con scope explícito.
3088
+ * Lo consume {@link ScopedLogger.span}.
3089
+ * @internal
3090
+ */
3091
+ async _runSpan(name, attributes, scope, fn) {
3092
+ const { record, span } = createSpan(name, attributes, scope, (r) => {
3093
+ this.transportBridge.writeRecord(r);
3094
+ });
3095
+ try {
3096
+ const result = await runWithActiveSpan(record, () => fn(span));
3097
+ span.end();
3098
+ return result;
3099
+ } catch (error) {
3100
+ span.fail(error);
3101
+ throw error;
3102
+ }
3103
+ }
3104
+ /**
1929
3105
  * Muestra datos en formato de tabla. Pasa por la pipeline completa
1930
3106
  * (outputMode-respecting writeOutput + transports + hooks).
1931
3107
  *
@@ -2034,7 +3210,7 @@ var Logger = class Logger {
2034
3210
  * Finaliza un temporizador y muestra el tiempo transcurrido
2035
3211
  *
2036
3212
  * @param {string} label - Etiqueta del temporizador a finalizar
2037
- * @returns {number} Elapsed milliseconds, or -1 if timer not found
3213
+ * @returns {number} Milisegundos transcurridos, o `-1` si no se encuentra el timer
2038
3214
  *
2039
3215
  * @example
2040
3216
  * logger.time('consulta-db');
@@ -2156,11 +3332,11 @@ var Logger = class Logger {
2156
3332
  } });
2157
3333
  }
2158
3334
  /**
2159
- * Displays a step progress indicator in the terminal
3335
+ * Muestra un indicador de progreso de pasos en la terminal
2160
3336
  *
2161
- * @param {number} current - Current step number
2162
- * @param {number} total - Total number of steps
2163
- * @param {string} message - Step description
3337
+ * @param {number} current - Número de paso actual
3338
+ * @param {number} total - Número total de pasos
3339
+ * @param {string} message - Descripción del paso
2164
3340
  *
2165
3341
  * @example
2166
3342
  * logger.step(1, 5, 'Analyzing repository...');
@@ -2171,10 +3347,10 @@ var Logger = class Logger {
2171
3347
  this.terminalBridge.step(current, total, message);
2172
3348
  }
2173
3349
  /**
2174
- * Displays a styled header with optional subtitle
3350
+ * Muestra un header con estilo y subtítulo opcional
2175
3351
  *
2176
- * @param {string} title - Main title text
2177
- * @param {string} subtitle - Optional subtitle (rendered dimmed)
3352
+ * @param {string} title - Texto del título principal
3353
+ * @param {string} subtitle - Subtítulo opcional (se renderiza atenuado)
2178
3354
  *
2179
3355
  * @example
2180
3356
  * logger.header('Commit Wizard', 'v2.0.0');
@@ -2184,7 +3360,7 @@ var Logger = class Logger {
2184
3360
  this.terminalBridge.header(title, subtitle);
2185
3361
  }
2186
3362
  /**
2187
- * Displays a horizontal divider line
3363
+ * Muestra una línea divisoria horizontal
2188
3364
  *
2189
3365
  * @example
2190
3366
  * logger.divider();
@@ -2194,7 +3370,7 @@ var Logger = class Logger {
2194
3370
  this.terminalBridge.divider();
2195
3371
  }
2196
3372
  /**
2197
- * Outputs a blank line
3373
+ * Emite una línea en blanco
2198
3374
  *
2199
3375
  * @example
2200
3376
  * logger.blank();
@@ -2204,10 +3380,10 @@ var Logger = class Logger {
2204
3380
  this.terminalBridge.blank();
2205
3381
  }
2206
3382
  /**
2207
- * Renders content inside a bordered box
3383
+ * Renderiza contenido dentro de un box con borde
2208
3384
  *
2209
- * @param {string} content - Content string (may contain newlines)
2210
- * @param {IBoxOptions} options - Box rendering options
3385
+ * @param {string} content - String de contenido (puede contener newlines)
3386
+ * @param {IBoxOptions} options - Opciones de renderizado del box
2211
3387
  *
2212
3388
  * @example
2213
3389
  * logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
@@ -2217,11 +3393,11 @@ var Logger = class Logger {
2217
3393
  this.terminalBridge.box(content, options);
2218
3394
  }
2219
3395
  /**
2220
- * Renders an array of objects as a formatted ASCII table.
2221
- * Note: This is distinct from the existing table() method which uses console.table.
3396
+ * Renderiza un array de objetos como una tabla ASCII formateada.
3397
+ * Distinto del método `table()` existente, que usa `console.table`.
2222
3398
  *
2223
- * @param {Record<string, unknown>[]} rows - Array of row objects
2224
- * @param {ITableOptions} options - Table rendering options
3399
+ * @param {Record<string, unknown>[]} rows - Array de objetos fila
3400
+ * @param {ITableOptions} options - Opciones de renderizado de la tabla
2225
3401
  *
2226
3402
  * @example
2227
3403
  * logger.cliTable([
@@ -2234,11 +3410,11 @@ var Logger = class Logger {
2234
3410
  this.terminalBridge.cliTable(rows, options);
2235
3411
  }
2236
3412
  /**
2237
- * Creates a spinner handle for showing progress during async operations.
2238
- * Returns a NoopSpinner in non-TTY environments.
3413
+ * Crea un handle de spinner para mostrar progreso durante operaciones async.
3414
+ * Devuelve un `NoopSpinner` en entornos non-TTY.
2239
3415
  *
2240
- * @param {string} message - Initial spinner text
2241
- * @returns {ISpinnerHandle} Spinner controller
3416
+ * @param {string} message - Texto inicial del spinner
3417
+ * @returns {ISpinnerHandle} Controller del spinner
2242
3418
  *
2243
3419
  * @example
2244
3420
  * const s = logger.spinner('Analyzing repository...');
@@ -2251,13 +3427,14 @@ var Logger = class Logger {
2251
3427
  return this.terminalBridge.spinner(message);
2252
3428
  }
2253
3429
  /**
2254
- * Sets the CLI verbosity level, controlling both log verbosity and primitive visibility
3430
+ * Fija el nivel de verbosidad del CLI, controlando a la vez la verbosidad
3431
+ * de logs y la visibilidad de las primitives
2255
3432
  *
2256
- * @param {CLILogLevel} level - CLI log level
3433
+ * @param {CLILogLevel} level - Nivel de log del CLI
2257
3434
  *
2258
3435
  * @example
2259
- * logger.setCLILevel('quiet'); // Only errors, no CLI primitives
2260
- * logger.setCLILevel('verbose'); // Debug logs + all CLI primitives
3436
+ * logger.setCLILevel('quiet'); // Solo errors, sin CLI primitives
3437
+ * logger.setCLILevel('verbose'); // Debug logs + todas las CLI primitives
2261
3438
  *
2262
3439
  */
2263
3440
  setCLILevel(level) {
@@ -2267,21 +3444,21 @@ var Logger = class Logger {
2267
3444
  this.config.cliLevel = level;
2268
3445
  }
2269
3446
  /**
2270
- * Returns the current CLI log level
2271
- * @returns {CLILogLevel} Current CLI log level
3447
+ * Devuelve el nivel de log del CLI actual
3448
+ * @returns {CLILogLevel} Nivel de log del CLI actual
2272
3449
  */
2273
3450
  get cliLevel() {
2274
3451
  return this.config.cliLevel ?? "normal";
2275
3452
  }
2276
3453
  /**
2277
- * Writes formatted output to the configured destination.
2278
- * Respects outputMode configuration for console, silent, or custom output.
3454
+ * Escribe output formateado al destino configurado.
3455
+ * Respeta la configuración `outputMode` para output a consola, silencioso o custom.
2279
3456
  *
2280
3457
  * @private
2281
- * @param {string} message - Formatted log message
2282
- * @param {LogLevel} level - Log level
2283
- * @param {string[]} styles - CSS styles for browser console
2284
- * @param {unknown[]} additionalArgs - Additional arguments to log
3458
+ * @param {string} message - Mensaje de log formateado
3459
+ * @param {LogLevel} level - Nivel de log
3460
+ * @param {string[]} styles - Estilos CSS para la consola del navegador
3461
+ * @param {unknown[]} additionalArgs - Argumentos adicionales a loggear
2285
3462
  */
2286
3463
  writeOutput(message, level, styles, additionalArgs) {
2287
3464
  const mode = this.config.outputMode ?? "console";
@@ -2321,21 +3498,20 @@ var Logger = class Logger {
2321
3498
  }
2322
3499
  };
2323
3500
  /**
2324
- /**
2325
- * Lazy singleton instance — initialised on first call to {@link getDefaultLogger},
2326
- * not on module import. Fixes BUG-N11 (eager side-effect at import time).
3501
+ * Instancia singleton lazy — se inicializa en la primera llamada a
3502
+ * {@link getDefaultLogger}, no al importar el módulo.
2327
3503
  *
2328
3504
  * @private
2329
3505
  */
2330
3506
  let _defaultLogger = null;
2331
3507
  /**
2332
- * Lazily creates the default Logger singleton.
3508
+ * Crea el singleton del Logger por defecto de forma lazy.
2333
3509
  *
2334
- * The singleton is only built on first call, so importing the module
2335
- * never executes `new Logger(...)` or `displayInitBanner()`. This keeps
2336
- * module imports side-effect free.
3510
+ * El singleton se construye solo en la primera llamada, de modo que
3511
+ * importar el módulo nunca ejecuta `new Logger(...)` ni
3512
+ * `displayInitBanner()`. Así los imports del módulo quedan side-effect free.
2337
3513
  *
2338
- * @returns The shared Logger instance
3514
+ * @returns La instancia compartida de Logger
2339
3515
  */
2340
3516
  function getDefaultLogger() {
2341
3517
  if (!_defaultLogger) {
@@ -2358,12 +3534,12 @@ new Proxy({}, { get(_target, prop, receiver) {
2358
3534
  return typeof value === "function" ? value.bind(instance) : value;
2359
3535
  } });
2360
3536
  /**
2361
- * Narrow a free-form `Record<string, unknown>` context into a typed
2362
- * `ILogAttributes` bag. Unknown shapes fall back to JSON-encoded strings,
2363
- * which keeps the OTLP transport happy (every value lands in a typed slot).
3537
+ * Estrecha un contexto free-form `Record<string, unknown>` a un bag tipado
3538
+ * `ILogAttributes`. Los shapes desconocidos caen a strings JSON-encoded,
3539
+ * lo que mantiene conforme al transport OTLP (cada valor cae en un slot tipado).
2364
3540
  *
2365
- * @param input - The user-supplied context (typically `Logger.context`).
2366
- * @returns A new attribute bag matching `ILogAttributes`.
3541
+ * @param input - Contexto suministrado por el usuario (típicamente `Logger.context`).
3542
+ * @returns Un nuevo bag de attributes que satisface `ILogAttributes`.
2367
3543
  */
2368
3544
  function toLogAttributes(input) {
2369
3545
  const out = {};
@@ -2390,6 +3566,23 @@ function toAttributeValue(value) {
2390
3566
  return;
2391
3567
  }
2392
3568
  }
3569
+ /**
3570
+ * Resuelve los argumentos del overload `span(name, fn?)` /
3571
+ * `span(name, attributes, fn)` a `{ attributes, fn }`.
3572
+ *
3573
+ * @internal Compartido con `ScopedLogger.span`; no es API pública.
3574
+ */
3575
+ function resolveSpanArgs(fnOrAttributes, maybeFn) {
3576
+ if (typeof fnOrAttributes === "function") return {
3577
+ attributes: void 0,
3578
+ fn: fnOrAttributes
3579
+ };
3580
+ if (typeof maybeFn === "function") return {
3581
+ attributes: fnOrAttributes,
3582
+ fn: maybeFn
3583
+ };
3584
+ throw new TypeError("span(name, …): se requiere una función fn");
3585
+ }
2393
3586
  //#endregion
2394
3587
  //#region src/index.ts
2395
3588
  /**
@@ -2422,6 +3615,11 @@ const group = (label, collapsed) => getLogger().group(label, collapsed);
2422
3615
  const groupEnd = () => getLogger().groupEnd();
2423
3616
  const time = (label) => getLogger().time(label);
2424
3617
  const timeEnd = (label) => getLogger().timeEnd(label);
3618
+ const event = (name, attributes) => getLogger().event(name, attributes);
3619
+ const startSpan = (name, attributes) => getLogger().startSpan(name, attributes);
3620
+ function span(name, fnOrAttributes, maybeFn) {
3621
+ return getLogger().span(name, fnOrAttributes, maybeFn);
3622
+ }
2425
3623
  const setGlobalPrefix = (prefix) => getLogger().setGlobalPrefix(prefix);
2426
3624
  const scope = (name) => getLogger().scope(name);
2427
3625
  const component = (name) => getLogger().component(name);
@@ -2480,6 +3678,7 @@ exports.critical = critical;
2480
3678
  exports.debug = debug;
2481
3679
  exports.default = src_default;
2482
3680
  exports.error = error;
3681
+ exports.event = event;
2483
3682
  exports.flushTransports = flushTransports;
2484
3683
  exports.formatLogLevelANSI = require_utils.formatLogLevelANSI;
2485
3684
  exports.formatSuccessANSI = require_utils.formatSuccessANSI;
@@ -2510,6 +3709,8 @@ exports.setGlobalPrefix = setGlobalPrefix;
2510
3709
  exports.setTheme = setTheme;
2511
3710
  exports.setVerbosity = setVerbosity;
2512
3711
  exports.showBanner = showBanner;
3712
+ exports.span = span;
3713
+ exports.startSpan = startSpan;
2513
3714
  exports.success = success;
2514
3715
  exports.supportsANSI = require_environment_detector.supportsANSI;
2515
3716
  exports.table = table;