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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +38 -336
  2. package/dist/Logger.d.ts +243 -154
  3. package/dist/Logger.d.ts.map +1 -1
  4. package/dist/ScopedLogger.d.ts +511 -8
  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-Cwn-1Zzb.js → LogContext-DjlITOzZ.js} +19 -4
  13. package/dist/chunks/LogContext-DjlITOzZ.js.map +1 -0
  14. package/dist/chunks/SerializerBridge-Ba43Mk7j.js +393 -0
  15. package/dist/chunks/SerializerBridge-Ba43Mk7j.js.map +1 -0
  16. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs +410 -0
  17. package/dist/chunks/SerializerBridge-C4a9Z37F.cjs.map +1 -0
  18. package/dist/chunks/{StyleManager-CIpd6wbO.cjs → StyleManager-DQ6UNRB-.cjs} +37 -11
  19. package/dist/chunks/StyleManager-DQ6UNRB-.cjs.map +1 -0
  20. package/dist/chunks/StyleManager-DjwAYbxE.js +113 -0
  21. package/dist/chunks/StyleManager-DjwAYbxE.js.map +1 -0
  22. package/dist/chunks/{core-PoT7RrTK.js → core-Blfi2klP.js} +1 -4
  23. package/dist/chunks/core-Blfi2klP.js.map +1 -0
  24. package/dist/chunks/{core-Dzz7agGa.cjs → core-CqS_UBzJ.cjs} +1 -4
  25. package/dist/chunks/core-CqS_UBzJ.cjs.map +1 -0
  26. package/dist/chunks/{environment-detector-CI3TrWK_.js → environment-detector-7NvnYUfr.js} +11 -11
  27. package/dist/chunks/environment-detector-7NvnYUfr.js.map +1 -0
  28. package/dist/chunks/{environment-detector-Cnn6wr6O.cjs → environment-detector-D-tHkKWA.cjs} +11 -11
  29. package/dist/chunks/environment-detector-D-tHkKWA.cjs.map +1 -0
  30. package/dist/chunks/server-fallback-CaCPjWby.cjs +119 -0
  31. package/dist/chunks/server-fallback-CaCPjWby.cjs.map +1 -0
  32. package/dist/chunks/server-fallback-jj0T6XaK.js +114 -0
  33. package/dist/chunks/server-fallback-jj0T6XaK.js.map +1 -0
  34. package/dist/chunks/{spinner-DNvxbM9a.cjs → spinner-BHyYEXsM.cjs} +319 -37
  35. package/dist/chunks/spinner-BHyYEXsM.cjs.map +1 -0
  36. package/dist/chunks/{spinner-D3FsF78o.js → spinner-BtkwpzYv.js} +319 -37
  37. package/dist/chunks/spinner-BtkwpzYv.js.map +1 -0
  38. package/dist/chunks/styling-CRw3KQW4.js +1592 -0
  39. package/dist/chunks/styling-CRw3KQW4.js.map +1 -0
  40. package/dist/chunks/styling-Cel2wPRy.cjs +1645 -0
  41. package/dist/chunks/styling-Cel2wPRy.cjs.map +1 -0
  42. package/dist/chunks/transports-BGfwwakw.js +1237 -0
  43. package/dist/chunks/transports-BGfwwakw.js.map +1 -0
  44. package/dist/chunks/transports-yK6CL0Ml.cjs +1278 -0
  45. package/dist/chunks/transports-yK6CL0Ml.cjs.map +1 -0
  46. package/dist/chunks/{utils-BqlFYocD.cjs → utils-W_cxqriN.cjs} +44 -37
  47. package/dist/chunks/utils-W_cxqriN.cjs.map +1 -0
  48. package/dist/chunks/{utils-VETbVpkR.js → utils-tKfBAWUM.js} +44 -37
  49. package/dist/chunks/utils-tKfBAWUM.js.map +1 -0
  50. package/dist/cli/CommandProcessor.d.ts +166 -19
  51. package/dist/cli/CommandProcessor.d.ts.map +1 -1
  52. package/dist/cli/commands/ConfigCommand.d.ts +36 -1
  53. package/dist/cli/commands/ConfigCommand.d.ts.map +1 -1
  54. package/dist/cli/commands/ExportCommand.d.ts +49 -3
  55. package/dist/cli/commands/ExportCommand.d.ts.map +1 -1
  56. package/dist/cli/commands/ThemeCommand.d.ts +62 -3
  57. package/dist/cli/commands/ThemeCommand.d.ts.map +1 -1
  58. package/dist/cli/help.d.ts +30 -2
  59. package/dist/cli/help.d.ts.map +1 -1
  60. package/dist/cli/index.d.ts +29 -2
  61. package/dist/cli/index.d.ts.map +1 -1
  62. package/dist/cli.cjs +2 -2
  63. package/dist/cli.js +2 -2
  64. package/dist/context/LogContext.d.ts +165 -66
  65. package/dist/context/LogContext.d.ts.map +1 -1
  66. package/dist/context.cjs +1 -1
  67. package/dist/context.js +1 -1
  68. package/dist/core.cjs +52 -29
  69. package/dist/core.cjs.map +1 -1
  70. package/dist/core.d.ts +50 -27
  71. package/dist/core.d.ts.map +1 -1
  72. package/dist/core.js +52 -29
  73. package/dist/core.js.map +1 -1
  74. package/dist/hooks/HookBridge.d.ts +15 -9
  75. package/dist/hooks/HookBridge.d.ts.map +1 -1
  76. package/dist/hooks/HookManager.d.ts +295 -2
  77. package/dist/hooks/HookManager.d.ts.map +1 -1
  78. package/dist/hooks.cjs +1 -1
  79. package/dist/hooks.js +1 -1
  80. package/dist/index.cjs +1092 -212
  81. package/dist/index.cjs.map +1 -1
  82. package/dist/index.js +1092 -212
  83. package/dist/index.js.map +1 -1
  84. package/dist/playground/TerminalBridge.d.ts +23 -16
  85. package/dist/playground/TerminalBridge.d.ts.map +1 -1
  86. package/dist/playground/box.d.ts +36 -5
  87. package/dist/playground/box.d.ts.map +1 -1
  88. package/dist/playground/cli-table.d.ts +41 -5
  89. package/dist/playground/cli-table.d.ts.map +1 -1
  90. package/dist/playground/divider.d.ts +22 -3
  91. package/dist/playground/divider.d.ts.map +1 -1
  92. package/dist/playground/header.d.ts +21 -4
  93. package/dist/playground/header.d.ts.map +1 -1
  94. package/dist/playground/server-fallback.d.ts +96 -9
  95. package/dist/playground/server-fallback.d.ts.map +1 -1
  96. package/dist/playground/spinner.d.ts +159 -10
  97. package/dist/playground/spinner.d.ts.map +1 -1
  98. package/dist/playground/step.d.ts +25 -6
  99. package/dist/playground/step.d.ts.map +1 -1
  100. package/dist/playground.cjs +1 -1
  101. package/dist/playground.js +1 -1
  102. package/dist/serializers/SerializerBridge.d.ts +13 -6
  103. package/dist/serializers/SerializerBridge.d.ts.map +1 -1
  104. package/dist/serializers/SerializerRegistry.d.ts +236 -0
  105. package/dist/serializers/SerializerRegistry.d.ts.map +1 -1
  106. package/dist/serializers.cjs +1 -1
  107. package/dist/serializers.js +1 -1
  108. package/dist/styles/StyleManager.d.ts +138 -31
  109. package/dist/styles/StyleManager.d.ts.map +1 -1
  110. package/dist/styles.cjs +2 -2
  111. package/dist/styles.js +2 -2
  112. package/dist/styling/SmartPresets.d.ts +100 -6
  113. package/dist/styling/SmartPresets.d.ts.map +1 -1
  114. package/dist/styling/StyleBuilder.d.ts +453 -32
  115. package/dist/styling/StyleBuilder.d.ts.map +1 -1
  116. package/dist/styling/banners.d.ts +83 -7
  117. package/dist/styling/banners.d.ts.map +1 -1
  118. package/dist/styling/themes.d.ts +41 -2
  119. package/dist/styling/themes.d.ts.map +1 -1
  120. package/dist/transports/ConsoleTransport.d.ts +95 -0
  121. package/dist/transports/ConsoleTransport.d.ts.map +1 -1
  122. package/dist/transports/FileTransport.d.ts +99 -18
  123. package/dist/transports/FileTransport.d.ts.map +1 -1
  124. package/dist/transports/HttpTransport.d.ts +135 -22
  125. package/dist/transports/HttpTransport.d.ts.map +1 -1
  126. package/dist/transports/OtlpTransport.d.ts +53 -36
  127. package/dist/transports/OtlpTransport.d.ts.map +1 -1
  128. package/dist/transports/TransportBridge.d.ts +19 -13
  129. package/dist/transports/TransportBridge.d.ts.map +1 -1
  130. package/dist/transports/TransportManager.d.ts +223 -8
  131. package/dist/transports/TransportManager.d.ts.map +1 -1
  132. package/dist/transports.cjs +1 -1
  133. package/dist/transports.js +1 -1
  134. package/dist/types/core.d.ts +155 -59
  135. package/dist/types/core.d.ts.map +1 -1
  136. package/dist/types/hooks.d.ts +92 -14
  137. package/dist/types/hooks.d.ts.map +1 -1
  138. package/dist/types/serializers.d.ts +72 -0
  139. package/dist/types/serializers.d.ts.map +1 -1
  140. package/dist/types/transports.d.ts +42 -37
  141. package/dist/types/transports.d.ts.map +1 -1
  142. package/dist/utils/ansi-colors.d.ts +15 -15
  143. package/dist/utils/environment-detector.d.ts +11 -11
  144. package/dist/utils/formatting.d.ts +8 -8
  145. package/dist/utils/output.d.ts +9 -9
  146. package/dist/utils/output.d.ts.map +1 -1
  147. package/dist/utils/stackTrace.d.ts +2 -2
  148. package/package.json +24 -25
  149. package/dist/chunks/HookBridge-CiRfR67f.cjs +0 -190
  150. package/dist/chunks/HookBridge-CiRfR67f.cjs.map +0 -1
  151. package/dist/chunks/HookBridge-SgMmbXZB.js +0 -173
  152. package/dist/chunks/HookBridge-SgMmbXZB.js.map +0 -1
  153. package/dist/chunks/LogContext-Cwn-1Zzb.js.map +0 -1
  154. package/dist/chunks/LogContext-L7HzynFw.cjs.map +0 -1
  155. package/dist/chunks/SerializerBridge-BaOQOb8q.cjs +0 -166
  156. package/dist/chunks/SerializerBridge-BaOQOb8q.cjs.map +0 -1
  157. package/dist/chunks/SerializerBridge-BkpQu5c9.js +0 -149
  158. package/dist/chunks/SerializerBridge-BkpQu5c9.js.map +0 -1
  159. package/dist/chunks/StyleManager-CIpd6wbO.cjs.map +0 -1
  160. package/dist/chunks/StyleManager-LCvVlVdx.js +0 -87
  161. package/dist/chunks/StyleManager-LCvVlVdx.js.map +0 -1
  162. package/dist/chunks/core-Dzz7agGa.cjs.map +0 -1
  163. package/dist/chunks/core-PoT7RrTK.js.map +0 -1
  164. package/dist/chunks/environment-detector-CI3TrWK_.js.map +0 -1
  165. package/dist/chunks/environment-detector-Cnn6wr6O.cjs.map +0 -1
  166. package/dist/chunks/server-fallback-BUKjdLS7.cjs +0 -42
  167. package/dist/chunks/server-fallback-BUKjdLS7.cjs.map +0 -1
  168. package/dist/chunks/server-fallback-BsuWH1Dk.js +0 -37
  169. package/dist/chunks/server-fallback-BsuWH1Dk.js.map +0 -1
  170. package/dist/chunks/spinner-D3FsF78o.js.map +0 -1
  171. package/dist/chunks/spinner-DNvxbM9a.cjs.map +0 -1
  172. package/dist/chunks/styling-84N8T97t.js +0 -941
  173. package/dist/chunks/styling-84N8T97t.js.map +0 -1
  174. package/dist/chunks/styling-Cg5saQ46.cjs +0 -994
  175. package/dist/chunks/styling-Cg5saQ46.cjs.map +0 -1
  176. package/dist/chunks/transports-BiDk345e.js +0 -715
  177. package/dist/chunks/transports-BiDk345e.js.map +0 -1
  178. package/dist/chunks/transports-COPWmlF1.cjs +0 -756
  179. package/dist/chunks/transports-COPWmlF1.cjs.map +0 -1
  180. package/dist/chunks/utils-BqlFYocD.cjs.map +0 -1
  181. package/dist/chunks/utils-VETbVpkR.js.map +0 -1
  182. package/dist/example.d.ts +0 -18
  183. package/dist/example.d.ts.map +0 -1
  184. package/dist/main.d.ts +0 -2
  185. package/dist/main.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { a as getTerminalWidth } from "./environment-detector-CI3TrWK_.js";
1
+ import { a as getTerminalWidth } from "./environment-detector-7NvnYUfr.js";
2
2
  //#region src/terminal/color-converter.ts
3
3
  const ANSI_16_COLORS = {
4
4
  black: {
@@ -427,12 +427,31 @@ function formatBadge(badge, style = "brackets", colorCapability = "full", color)
427
427
  * @fileoverview Step progress renderer for CLI primitives
428
428
  */
429
429
  /**
430
- * Renders a step progress indicator like ` [2/5] Analyzing repository...`
431
- * @param current - Current step number
432
- * @param total - Total number of steps
433
- * @param msg - Step description message
434
- * @param colorCap - Terminal color capability
435
- * @returns Formatted step string
430
+ * Renderiza un indicador de progreso de step con el formato ` [n/total] msg`,
431
+ * donde el `[n/total]` se emite en cian bold (respetando `colorCap`) para
432
+ * destacarlo del mensaje descriptivo. Pensado para output secuencial de CLI
433
+ * tipo "steps de un build", "fases de un deploy" o "tareas de un script".
434
+ *
435
+ * No hace ningún chequeo de rango sobre `current`/`total` — el caller es
436
+ * responsable de pasar valores coherentes (se renderizan tal cual).
437
+ *
438
+ * @param current - Número de step actual (típicamente 1-based).
439
+ * @param total - Total de steps del proceso.
440
+ * @param msg - Descripción corta del step en curso.
441
+ * @param colorCap - Capacidad de color del terminal destino. Si es `'none'`,
442
+ * el label `[n/total]` se emite sin color.
443
+ * @returns String de una sola línea con formato ` [n/total] msg`.
444
+ *
445
+ * @example
446
+ * ```ts
447
+ * const steps = ['Resolving deps', 'Bundling', 'Writing dist'];
448
+ * steps.forEach((step, i) => {
449
+ * process.stdout.write(renderStep(i + 1, steps.length, step, 'full') + '\n');
450
+ * });
451
+ * // [1/3] Resolving deps
452
+ * // [2/3] Bundling
453
+ * // [3/3] Writing dist
454
+ * ```
436
455
  */
437
456
  function renderStep(current, total, msg, colorCap) {
438
457
  const label = `[${current}/${total}]`;
@@ -444,10 +463,27 @@ function renderStep(current, total, msg, colorCap) {
444
463
  * @fileoverview Header renderer for CLI primitives
445
464
  */
446
465
  /**
447
- * Renders a styled header with optional subtitle
448
- * @param title - Main title text
449
- * @param subtitle - Optional subtitle (rendered dimmed)
450
- * @returns Formatted header string
466
+ * Renderiza un header de sección: `title` en bold seguido opcionalmente de
467
+ * `subtitle` en dim (ANSI `2`), ideal para marcar bloques en output de CLI.
468
+ * No usa colores de foreground — sólo atributos de texto, así que el renderer
469
+ * es seguro para cualquier terminal sin importar la paleta del theme activo.
470
+ *
471
+ * @param title - Texto principal del header (siempre en bold).
472
+ * @param subtitle - Texto secundario a la derecha del título; se renderiza
473
+ * dimmed y separado por un espacio. Omitir si no aplica.
474
+ * @returns String de una línea con formato ` <bold>title</bold> <dim>subtitle</dim>`.
475
+ *
476
+ * @example
477
+ * ```ts
478
+ * process.stdout.write(renderHeader('Deploy', 'production · us-east-1') + '\n');
479
+ * // **Deploy** production · us-east-1 (con atributos ANSI aplicados)
480
+ * ```
481
+ *
482
+ * @example
483
+ * ```ts
484
+ * // Header sin subtítulo
485
+ * process.stdout.write(renderHeader('Build summary') + '\n');
486
+ * ```
451
487
  */
452
488
  function renderHeader(title, subtitle) {
453
489
  return ` ${ANSI.bold + title + ANSI.reset}${subtitle ? ANSI.dim + ` ${subtitle}` + ANSI.reset : ""}`;
@@ -458,9 +494,28 @@ function renderHeader(title, subtitle) {
458
494
  * @fileoverview Divider renderer for CLI primitives
459
495
  */
460
496
  /**
461
- * Renders a horizontal divider line
462
- * @param width - Optional explicit width (defaults to terminal width capped at 60)
463
- * @returns Formatted divider string
497
+ * Renderiza una línea divisoria horizontal dimmed (ANSI `2`) usando el
498
+ * caracter `─`. Por defecto el ancho es `min(terminalWidth - 4, 60)` para
499
+ * no ocupar todo el ancho de ventana y quedar visualmente alineado con otros
500
+ * primitives (box, header, table) que dejan 2 espacios de indentación.
501
+ *
502
+ * @param width - Ancho explícito en columnas visibles. Si se omite, se calcula
503
+ * automáticamente a partir del ancho del terminal (capped a 60).
504
+ * @returns String de una línea con `width` caracteres `─` envueltos en ANSI dim.
505
+ *
506
+ * @example
507
+ * ```ts
508
+ * // Divider automático (respeta el ancho del terminal)
509
+ * process.stdout.write(renderDivider() + '\n');
510
+ * ```
511
+ *
512
+ * @example
513
+ * ```ts
514
+ * // Divider de ancho fijo para alinear con otra salida
515
+ * process.stdout.write(renderDivider(40) + '\n');
516
+ * ```
517
+ *
518
+ * @see {@link getTerminalWidth} para la detección de ancho cuando `width` se omite.
464
519
  */
465
520
  function renderDivider(width) {
466
521
  const w = width ?? Math.min(getTerminalWidth() - 4, 60);
@@ -469,7 +524,16 @@ function renderDivider(width) {
469
524
  //#endregion
470
525
  //#region src/playground/box.ts
471
526
  /**
472
- * Border character sets for different styles
527
+ * Mapa de juegos de caracteres Unicode para los 4 estilos de borde soportados
528
+ * por {@link renderBox}. Cada entrada expone las 4 esquinas (`tl`, `tr`, `bl`,
529
+ * `br`), el caracter horizontal (`h`) y el vertical (`v`) que componen el marco.
530
+ *
531
+ * - `single`: l\u00edneas finas (U+2500 / U+2502).
532
+ * - `rounded`: igual que `single` con esquinas redondeadas.
533
+ * - `double`: l\u00edneas dobles (U+2550 / U+2551), alto contraste visual.
534
+ * - `bold`: l\u00edneas gruesas (U+2501 / U+2503), para destacar bloques cr\u00edticos.
535
+ *
536
+ * @internal Lookup interno del renderer; no es API p\u00fablica.
473
537
  */
474
538
  const BORDER_CHARS = {
475
539
  single: {
@@ -506,11 +570,42 @@ const BORDER_CHARS = {
506
570
  }
507
571
  };
508
572
  /**
509
- * Renders content inside a bordered box
510
- * @param content - Content string (may contain newlines)
511
- * @param options - Box rendering options
512
- * @param colorCap - Terminal color capability
513
- * @returns Formatted box string with border
573
+ * Renderiza `content` envuelto en un box con borde Unicode, respetando el
574
+ * ancho del terminal. El ancho interno se calcula a partir de la l\u00ednea m\u00e1s
575
+ * larga (o del {@link IBoxOptions.title} si es m\u00e1s ancho) y se acota a
576
+ * `min(terminalWidth - 4, 80)` columnas para no romper layouts estrechos.
577
+ *
578
+ * El padding se aplica como l\u00edneas vac\u00edas sim\u00e9tricas arriba/abajo del
579
+ * contenido. Si `borderColor` se omite o `colorCap` es `'none'`, el borde se
580
+ * emite sin secuencias ANSI (output plain-text seguro para logs y pipes).
581
+ *
582
+ * @param content - Texto a envolver; puede contener m\u00faltiples l\u00edneas (`\n`) y
583
+ * secuencias ANSI embebidas \u2014 el c\u00e1lculo de ancho usa el largo visible.
584
+ * @param options - Configuraci\u00f3n del box (title, borderColor, borderStyle,
585
+ * padding). Ver {@link IBoxOptions}.
586
+ * @param colorCap - Capacidad de color del terminal destino. Si es `'none'`,
587
+ * se omite cualquier secuencia ANSI.
588
+ * @returns String multilinea con el box ya construido (sin trailing newline).
589
+ *
590
+ * @example
591
+ * ```ts
592
+ * // Box b\u00e1sico con borde redondeado (default)
593
+ * process.stdout.write(renderBox('Deploy completado') + '\n');
594
+ * ```
595
+ *
596
+ * @example
597
+ * ```ts
598
+ * // Box con t\u00edtulo embebido en el borde superior y color custom
599
+ * process.stdout.write(renderBox('Service: auth-svc\nStatus: healthy', {
600
+ * title: 'Health Check',
601
+ * borderColor: '#00bcd4',
602
+ * borderStyle: 'double',
603
+ * padding: 1
604
+ * }) + '\n');
605
+ * ```
606
+ *
607
+ * @see {@link IBoxOptions} para el detalle de cada opci\u00f3n.
608
+ * @see {@link getTerminalWidth} para la detecci\u00f3n de ancho.
514
609
  */
515
610
  function renderBox(content, options = {}, colorCap = "full") {
516
611
  const { title, borderColor, borderStyle = "rounded", padding = 0 } = options;
@@ -549,11 +644,47 @@ function renderBox(content, options = {}, colorCap = "full") {
549
644
  //#endregion
550
645
  //#region src/playground/cli-table.ts
551
646
  /**
552
- * Renders an array of objects as a formatted ASCII table
553
- * @param rows - Array of row objects
554
- * @param options - Table rendering options
555
- * @param colorCap - Terminal color capability
556
- * @returns Formatted table string
647
+ * Renderiza un array de objetos como tabla ASCII alineada, con headers en
648
+ * cian bold y separador (`─`) bajo la cabecera. Las columnas se autodetectan
649
+ * a partir de las keys del primer row salvo que `options.columns` las imponga,
650
+ * y los labels se toman de `options.head` (default: nombres de columna).
651
+ *
652
+ * El ancho de cada columna se calcula como `max(header, valor más largo) + 2`
653
+ * para garantizar padding horizontal consistente. Si `colorCap` es `'none'`,
654
+ * se omiten todas las secuencias ANSI (útil para logs plain-text o CI).
655
+ *
656
+ * @param rows - Array de row objects. Un array vacío devuelve string vacío.
657
+ * @param options - Ver {@link ITableOptions} para `columns` y `head`.
658
+ * @param colorCap - Capacidad de color del terminal destino.
659
+ * @returns String multilinea con la tabla (header + separator + data rows),
660
+ * o `''` si `rows` está vacío.
661
+ *
662
+ * @example
663
+ * ```ts
664
+ * // Auto-detect columnas desde las keys del primer row
665
+ * const rows = [
666
+ * { service: 'auth', status: 'healthy', latency: 12 },
667
+ * { service: 'api', status: 'degraded', latency: 245 }
668
+ * ];
669
+ * process.stdout.write(renderTable(rows) + '\n');
670
+ * // ┌─────────┬──────────┬─────────┐
671
+ * // │ service │ status │ latency │
672
+ * // ─────────────────────────────────
673
+ * // │ auth │ healthy │ 12 │
674
+ * // │ api │ degraded │ 245 │
675
+ * ```
676
+ *
677
+ * @example
678
+ * ```ts
679
+ * // Forzar columnas y renombrar headers
680
+ * process.stdout.write(renderTable(rows, {
681
+ * columns: ['service', 'latency'],
682
+ * head: ['Service', 'Latency (ms)']
683
+ * }, 'none') + '\n');
684
+ * ```
685
+ *
686
+ * @see {@link ITableOptions} para las opciones disponibles.
687
+ * @see {@link getVisibleLength} y {@link padToWidth} para el cálculo de ancho.
557
688
  */
558
689
  function renderTable(rows, options = {}, colorCap = "full") {
559
690
  if (rows.length === 0) return "";
@@ -585,7 +716,12 @@ function renderTable(rows, options = {}, colorCap = "full") {
585
716
  }
586
717
  //#endregion
587
718
  //#region src/playground/spinner.ts
588
- /** Braille-based spinner animation frames */
719
+ /**
720
+ * Frames braille usados por la animaci\u00f3n del spinner. Cada frame es un
721
+ * car\u00e1cter del bloque Unicode Braille Patterns (U+2800\u2013U+28FF) que da la
722
+ * ilusi\u00f3n de rotaci\u00f3n al ciclarlos a ~12 FPS. Elegidos sobre caracteres
723
+ * ASCII (`|/-\`) porque renderizan m\u00e1s suaves en terminales modernas.
724
+ */
589
725
  const SPINNER_FRAMES = [
590
726
  "⠋",
591
727
  "⠙",
@@ -598,24 +734,68 @@ const SPINNER_FRAMES = [
598
734
  "⠇",
599
735
  "⠏"
600
736
  ];
601
- /** Spinner frame interval in milliseconds */
737
+ /**
738
+ * Intervalo entre frames del spinner en milisegundos. 80 ms \u2248 12.5 FPS:
739
+ * suficientemente r\u00e1pido para sentirse responsivo sin consumir CPU
740
+ * perceptiblemente en runs largos.
741
+ */
602
742
  const FRAME_INTERVAL = 80;
603
743
  /**
604
- * Interactive terminal spinner with in-place line updates.
605
- * Writes to stderr to avoid polluting piped stdout.
744
+ * Spinner interactivo para TTY: cicla frames braille reescribiendo la l\u00ednea
745
+ * actual en su sitio (no emite l\u00edneas nuevas hasta el stop).
746
+ *
747
+ * Para no poluir stdout piped ni entrelazarse con el output normal del
748
+ * {@link Logger}, hace dos cosas no obvias:
749
+ * 1. Escribe SIEMPRE a `process.stderr` (carriage return + `\x1b[K` para
750
+ * limpiar la l\u00ednea antes de cada render).
751
+ * 2. Con `start()` mutea el logger (`outputMode: 'silent'`) y lo restaura a
752
+ * `'console'` en cualquier m\u00e9todo de finalizaci\u00f3n (`stop`/`succeed`/`fail`).
753
+ * Sin esto, los logs del usuario se imprimir\u00edan encima del frame animado.
754
+ *
755
+ * No gestiona TTY detection \u2014 quien lo instancia (`TerminalBridge`) ya valid\u00f3
756
+ * que hay TTY. Para non-TTY ver {@link NoopSpinner}.
606
757
  *
607
758
  * @implements {ISpinnerHandle}
759
+ *
760
+ * @example
761
+ * ```ts
762
+ * const spinner = new SpinnerManager('Compilando...', logger.config, logger);
763
+ * spinner.start();
764
+ * // ...trabajo as\u00edncrono...
765
+ * spinner.succeed('Build OK');
766
+ * // stderr: " \u2713 Build OK"
767
+ * ```
768
+ *
769
+ * @see {@link NoopSpinner} para el path non-TTY.
770
+ * @see {@link ISpinnerHandle} para el contrato de la API p\u00fablica.
608
771
  */
609
772
  var SpinnerManager = class {
610
773
  message;
611
774
  frameIndex = 0;
612
775
  interval = null;
613
776
  _logger;
777
+ /**
778
+ * @param {string} message - Texto a mostrar al lado del frame animado.
779
+ * Mutables luego v\u00eda {@link SpinnerManager.text}.
780
+ * @param {LoggerConfig} _config - Reservado para configuraci\u00f3n futura;
781
+ * actualmente no se lee dentro de la clase (lo conserva solo el caller).
782
+ * @param {Logger} logger - Instancia del logger due\u00f1a del spinner. Se
783
+ * mutea/restaura con `updateConfig({ outputMode })` en start/stop.
784
+ */
614
785
  constructor(message, _config, logger) {
615
786
  this.message = message;
616
787
  this._logger = logger;
617
788
  }
618
- /** Start the spinner animation */
789
+ /**
790
+ * Arranca la animaci\u00f3n. Idempotente: si ya est\u00e1 corriendo, no hace nada.
791
+ *
792
+ * Como efecto lateral mutea el logger pasado al constructor cambiando su
793
+ * `outputMode` a `'silent'` \u2014 cualquier log durante la animaci\u00f3n quedar\u00eda
794
+ * bufferizado y se descarta al restaurar el modo. Llama siempre a
795
+ * {@link stop}, {@link succeed} o {@link fail} para restaurar el output.
796
+ *
797
+ * @returns {void}
798
+ */
619
799
  start() {
620
800
  if (this.interval) return;
621
801
  this._logger.updateConfig({ outputMode: "silent" });
@@ -626,13 +806,36 @@ var SpinnerManager = class {
626
806
  this.render();
627
807
  }, FRAME_INTERVAL);
628
808
  }
629
- /** Stop the spinner without a status message */
809
+ /**
810
+ * Detiene la animaci\u00f3n y limpia la l\u00ednea, sin emitir mensaje de estado.
811
+ * Restaura el `outputMode` del logger a `'console'`.
812
+ *
813
+ * \u00datil cuando el caller ya emiti\u00f3 su propio output final y solo necesita
814
+ * desmontar el spinner. Para terminaci\u00f3n con tick/cross usa
815
+ * {@link succeed} / {@link fail}.
816
+ *
817
+ * @returns {void}
818
+ */
630
819
  stop() {
631
820
  this.clearInterval();
632
821
  this.clearLine();
633
822
  this._logger.updateConfig({ outputMode: "console" });
634
823
  }
635
- /** Stop with a success indicator */
824
+ /**
825
+ * Detiene la animaci\u00f3n y emite el mensaje con un check verde (`\u2713`).
826
+ * Restaura el `outputMode` del logger a `'console'`.
827
+ *
828
+ * @param {string} [msg] - Texto final a mostrar. Si se omite, reutiliza
829
+ * el `message` con el que se construy\u00f3 el spinner (o el \u00faltimo seteado
830
+ * v\u00eda {@link text}).
831
+ * @returns {void}
832
+ *
833
+ * @example
834
+ * ```ts
835
+ * spinner.succeed(); // \u2192 " \u2713 <message inicial>"
836
+ * spinner.succeed('Hecho'); // \u2192 " \u2713 Hecho"
837
+ * ```
838
+ */
636
839
  succeed(msg) {
637
840
  this.clearInterval();
638
841
  this.clearLine();
@@ -640,7 +843,25 @@ var SpinnerManager = class {
640
843
  process.stderr.write(` ${ANSI.fg.green}\u2713${ANSI.reset} ${text}\n`);
641
844
  this._logger.updateConfig({ outputMode: "console" });
642
845
  }
643
- /** Stop with a failure indicator */
846
+ /**
847
+ * Detiene la animaci\u00f3n y emite el mensaje con una cruz roja (`\u2717`).
848
+ * Restaura el `outputMode` del logger a `'console'`.
849
+ *
850
+ * @param {string} [msg] - Texto final a mostrar. Si se omite, reutiliza
851
+ * el `message` con el que se construy\u00f3 el spinner (o el \u00faltimo seteado
852
+ * v\u00eda {@link text}).
853
+ * @returns {void}
854
+ *
855
+ * @example
856
+ * ```ts
857
+ * try {
858
+ * await build();
859
+ * spinner.succeed('Build OK');
860
+ * } catch (e) {
861
+ * spinner.fail(`Build fallido: ${e.message}`);
862
+ * }
863
+ * ```
864
+ */
644
865
  fail(msg) {
645
866
  this.clearInterval();
646
867
  this.clearLine();
@@ -648,7 +869,14 @@ var SpinnerManager = class {
648
869
  process.stderr.write(` ${ANSI.fg.red}\u2717${ANSI.reset} ${text}\n`);
649
870
  this._logger.updateConfig({ outputMode: "console" });
650
871
  }
651
- /** Update the spinner text while running */
872
+ /**
873
+ * Reemplaza el texto mostrado al lado del frame sin reiniciar la animaci\u00f3n
874
+ * ni perder el frame actual. Pensado para actualizar progreso in-place
875
+ * (p.ej. contador de items procesados).
876
+ *
877
+ * @param {string} msg - Nuevo texto a mostrar.
878
+ * @returns {void}
879
+ */
652
880
  text(msg) {
653
881
  this.message = msg;
654
882
  }
@@ -668,28 +896,82 @@ var SpinnerManager = class {
668
896
  }
669
897
  };
670
898
  /**
671
- * No-op spinner for non-TTY environments or silent mode.
672
- * Logs start/succeed/fail as plain log messages.
899
+ * Spinner degenerate para non-TTY (CI logs, pipes, `outputMode: 'silent'`).
900
+ *
901
+ * No anima nada: traduce los eventos del ciclo de vida del spinner a llamadas
902
+ * normales del logger (`info` en start, `success`/`error` en finish). Así el
903
+ * consumidor mantiene la misma API {@link ISpinnerHandle} sin saber si está
904
+ * corriendo en terminal interactiva o en un job de CI.
905
+ *
906
+ * A diferencia de {@link SpinnerManager}, **no** toca el `outputMode` del
907
+ * logger — no hay nada que mutear porque no hay frame animado que proteger.
673
908
  *
674
909
  * @implements {ISpinnerHandle}
910
+ *
911
+ * @example
912
+ * ```ts
913
+ * // En CI (sin TTY) el TerminalBridge entrega un NoopSpinner automáticamente:
914
+ * const s = logger.spinner('Running tests...');
915
+ * s.start(); // logger.info('Running tests...')
916
+ * s.succeed('All green'); // logger.success('All green')
917
+ * ```
918
+ *
919
+ * @see {@link SpinnerManager} para el path interactivo con animación.
675
920
  */
676
921
  var NoopSpinner = class {
677
922
  message;
678
923
  _logger;
924
+ /**
925
+ * @param {string} message - Texto base; se reutiliza como mensaje final
926
+ * si {@link succeed} / {@link fail} se llaman sin argumento.
927
+ * @param {Logger} logger - Logger sobre el que se emiten los eventos.
928
+ */
679
929
  constructor(message, logger) {
680
930
  this.message = message;
681
931
  this._logger = logger;
682
932
  }
933
+ /**
934
+ * Emite el mensaje inicial como `logger.info(...)`. No arranca ningún
935
+ * timer — en non-TTY no hay nada que animar.
936
+ *
937
+ * @returns {void}
938
+ */
683
939
  start() {
684
940
  this._logger.info(this.message);
685
941
  }
942
+ /**
943
+ * No-op — no hay animación que detener ni output que restaurar.
944
+ *
945
+ * @returns {void}
946
+ */
686
947
  stop() {}
948
+ /**
949
+ * Emite el mensaje final como `logger.success(...)`.
950
+ *
951
+ * @param {string} [msg] - Texto final; si se omite usa el `message`
952
+ * inicial o el último seteado vía {@link text}.
953
+ * @returns {void}
954
+ */
687
955
  succeed(msg) {
688
956
  this._logger.success(msg ?? this.message);
689
957
  }
958
+ /**
959
+ * Emite el mensaje final como `logger.error(...)`.
960
+ *
961
+ * @param {string} [msg] - Texto final; si se omite usa el `message`
962
+ * inicial o el último seteado vía {@link text}.
963
+ * @returns {void}
964
+ */
690
965
  fail(msg) {
691
966
  this._logger.error(msg ?? this.message);
692
967
  }
968
+ /**
969
+ * Actualiza el mensaje interno (sin output). Solo afecta al texto que
970
+ * emitirán {@link succeed} / {@link fail} cuando se invoquen sin argumento.
971
+ *
972
+ * @param {string} msg - Nuevo texto base.
973
+ * @returns {void}
974
+ */
693
975
  text(msg) {
694
976
  this.message = msg;
695
977
  }
@@ -697,4 +979,4 @@ var NoopSpinner = class {
697
979
  //#endregion
698
980
  export { renderDivider as a, formatBadge as c, renderBox as i, SpinnerManager as n, renderHeader as o, renderTable as r, renderStep as s, NoopSpinner as t };
699
981
 
700
- //# sourceMappingURL=spinner-D3FsF78o.js.map
982
+ //# sourceMappingURL=spinner-BtkwpzYv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spinner-BtkwpzYv.js","names":[],"sources":["../../src/terminal/color-converter.ts","../../src/terminal/formatter.ts","../../src/playground/step.ts","../../src/playground/header.ts","../../src/playground/divider.ts","../../src/playground/box.ts","../../src/playground/cli-table.ts","../../src/playground/spinner.ts"],"sourcesContent":["/**\n * Color Converter - CSS colors to ANSI extended color codes\n * Supports 256-color and truecolor (24-bit) terminals\n */\n\nexport type ColorCapability = 'full' | 'basic' | 'none';\n\nexport interface RGB {\n r: number;\n g: number;\n b: number;\n}\n\nconst ANSI_16_COLORS: Record<string, { fg: string; bg: string; bright: { fg: string; bg: string } }> = {\n black: { fg: '30', bg: '40', bright: { fg: '90', bg: '100' } },\n red: { fg: '31', bg: '41', bright: { fg: '91', bg: '101' } },\n green: { fg: '32', bg: '42', bright: { fg: '92', bg: '102' } },\n yellow: { fg: '33', bg: '43', bright: { fg: '93', bg: '103' } },\n blue: { fg: '34', bg: '44', bright: { fg: '94', bg: '104' } },\n magenta: { fg: '35', bg: '45', bright: { fg: '95', bg: '105' } },\n cyan: { fg: '36', bg: '46', bright: { fg: '96', bg: '106' } },\n white: { fg: '37', bg: '47', bright: { fg: '97', bg: '107' } },\n gray: { fg: '90', bg: '100', bright: { fg: '37', bg: '47' } },\n grey: { fg: '90', bg: '100', bright: { fg: '37', bg: '47' } },\n};\n\nconst CSS_NAMED_COLORS: Record<string, string> = {\n aliceblue: '#f0f8ff', antiquewhite: '#faebd7', aqua: '#00ffff',\n aquamarine: '#7fffd4', azure: '#f0ffff', beige: '#f5f5dc',\n bisque: '#ffe4c4', black: '#000000', blanchedalmond: '#ffebcd',\n blue: '#0000ff', blueviolet: '#8a2be2', brown: '#a52a2a',\n burlywood: '#deb887', cadetblue: '#5f9ea0', chartreuse: '#7fff00',\n chocolate: '#d2691e', coral: '#ff7f50', cornflowerblue: '#6495ed',\n cornsilk: '#fff8dc', crimson: '#dc143c', cyan: '#00ffff',\n darkblue: '#00008b', darkcyan: '#008b8b', darkgoldenrod: '#b8860b',\n darkgray: '#a9a9a9', darkgreen: '#006400', darkkhaki: '#bdb76b',\n darkmagenta: '#8b008b', darkolivegreen: '#556b2f', darkorange: '#ff8c00',\n darkorchid: '#9932cc', darkred: '#8b0000', darksalmon: '#e9967a',\n darkseagreen: '#8fbc8f', darkslateblue: '#483d8b', darkslategray: '#2f4f4f',\n darkturquoise: '#00ced1', darkviolet: '#9400d3', deeppink: '#ff1493',\n deepskyblue: '#00bfff', dimgray: '#696969', dodgerblue: '#1e90ff',\n firebrick: '#b22222', floralwhite: '#fffaf0', forestgreen: '#228b22',\n fuchsia: '#ff00ff', gainsboro: '#dcdcdc', ghostwhite: '#f8f8ff',\n gold: '#ffd700', goldenrod: '#daa520', gray: '#808080',\n green: '#008000', greenyellow: '#adff2f', honeydew: '#f0fff0',\n hotpink: '#ff69b4', indianred: '#cd5c5c', indigo: '#4b0082',\n ivory: '#fffff0', khaki: '#f0e68c', lavender: '#e6e6fa',\n lavenderblush: '#fff0f5', lawngreen: '#7cfc00', lemonchiffon: '#fffacd',\n lightblue: '#add8e6', lightcoral: '#f08080', lightcyan: '#e0ffff',\n lightgoldenrodyellow: '#fafad2', lightgray: '#d3d3d3', lightgreen: '#90ee90',\n lightpink: '#ffb6c1', lightsalmon: '#ffa07a', lightseagreen: '#20b2aa',\n lightskyblue: '#87cefa', lightslategray: '#778899', lightsteelblue: '#b0c4de',\n lightyellow: '#ffffe0', lime: '#00ff00', limegreen: '#32cd32',\n linen: '#faf0e6', magenta: '#ff00ff', maroon: '#800000',\n mediumaquamarine: '#66cdaa', mediumblue: '#0000cd', mediumorchid: '#ba55d3',\n mediumpurple: '#9370db', mediumseagreen: '#3cb371', mediumslateblue: '#7b68ee',\n mediumspringgreen: '#00fa9a', mediumturquoise: '#48d1cc', mediumvioletred: '#c71585',\n midnightblue: '#191970', mintcream: '#f5fffa', mistyrose: '#ffe4e1',\n moccasin: '#ffe4b5', navajowhite: '#ffdead', navy: '#000080',\n oldlace: '#fdf5e6', olive: '#808000', olivedrab: '#6b8e23',\n orange: '#ffa500', orangered: '#ff4500', orchid: '#da70d6',\n palegoldenrod: '#eee8aa', palegreen: '#98fb98', paleturquoise: '#afeeee',\n palevioletred: '#db7093', papayawhip: '#ffefd5', peachpuff: '#ffdab9',\n peru: '#cd853f', pink: '#ffc0cb', plum: '#dda0dd',\n powderblue: '#b0e0e6', purple: '#800080', rebeccapurple: '#663399',\n red: '#ff0000', rosybrown: '#bc8f8f', royalblue: '#4169e1',\n saddlebrown: '#8b4513', salmon: '#fa8072', sandybrown: '#f4a460',\n seagreen: '#2e8b57', seashell: '#fff5ee', sienna: '#a0522d',\n silver: '#c0c0c0', skyblue: '#87ceeb', slateblue: '#6a5acd',\n slategray: '#708090', snow: '#fffafa', springgreen: '#00ff7f',\n steelblue: '#4682b4', tan: '#d2b48c', teal: '#008080',\n thistle: '#d8bfd8', tomato: '#ff6347', turquoise: '#40e0d0',\n violet: '#ee82ee', wheat: '#f5deb3', white: '#ffffff',\n whitesmoke: '#f5f5f5', yellow: '#ffff00', yellowgreen: '#9acd32',\n};\n\nexport function hexToRgb(hex: string): RGB {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n if (!result || !result[1] || !result[2] || !result[3]) {\n return { r: 255, g: 255, b: 255 };\n }\n return {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16),\n };\n}\n\nexport function rgbToHex(r: number, g: number, b: number): string {\n return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');\n}\n\nexport function hexTo256(hex: string): number {\n const { r, g, b } = hexToRgb(hex);\n\n if (r === g && g === b) {\n if (r < 8) return 16;\n if (r > 248) return 231;\n return Math.round(((r - 8) / 247) * 24) + 232;\n }\n\n const ri = Math.round(r / 255 * 5);\n const gi = Math.round(g / 255 * 5);\n const bi = Math.round(b / 255 * 5);\n\n return 16 + (36 * ri) + (6 * gi) + bi;\n}\n\nexport function colorToHex(color: string): string {\n if (color.startsWith('#')) {\n return color;\n }\n\n const named = CSS_NAMED_COLORS[color.toLowerCase()];\n if (named) {\n return named;\n }\n\n const rgbMatch = color.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (rgbMatch && rgbMatch[1] && rgbMatch[2] && rgbMatch[3]) {\n return rgbToHex(\n parseInt(rgbMatch[1]),\n parseInt(rgbMatch[2]),\n parseInt(rgbMatch[3])\n );\n }\n\n return '#ffffff';\n}\n\nexport function getANSIForeground(color: string, capability: ColorCapability): string {\n if (capability === 'none') return '';\n\n const lowerColor = color.toLowerCase();\n\n if (capability === 'basic' && ANSI_16_COLORS[lowerColor]) {\n return `\\x1b[${ANSI_16_COLORS[lowerColor].fg}m`;\n }\n\n if (capability === 'basic') {\n const hex = colorToHex(color);\n const nearestBasic = findNearestBasicColor(hex);\n const basicColor = ANSI_16_COLORS[nearestBasic];\n return basicColor ? `\\x1b[${basicColor.fg}m` : '\\x1b[37m';\n }\n\n const hex = colorToHex(color);\n const { r, g, b } = hexToRgb(hex);\n return `\\x1b[38;2;${r};${g};${b}m`;\n}\n\nexport function getANSIBackground(color: string, capability: ColorCapability): string {\n if (capability === 'none') return '';\n\n const lowerColor = color.toLowerCase();\n\n if (capability === 'basic' && ANSI_16_COLORS[lowerColor]) {\n return `\\x1b[${ANSI_16_COLORS[lowerColor].bg}m`;\n }\n\n if (capability === 'basic') {\n const hex = colorToHex(color);\n const nearestBasic = findNearestBasicColor(hex);\n const basicColor = ANSI_16_COLORS[nearestBasic];\n return basicColor ? `\\x1b[${basicColor.bg}m` : '\\x1b[47m';\n }\n\n const hex = colorToHex(color);\n const { r, g, b } = hexToRgb(hex);\n return `\\x1b[48;2;${r};${g};${b}m`;\n}\n\nexport function getANSI256Foreground(colorIndex: number): string {\n return `\\x1b[38;5;${colorIndex}m`;\n}\n\nexport function getANSI256Background(colorIndex: number): string {\n return `\\x1b[48;5;${colorIndex}m`;\n}\n\nfunction findNearestBasicColor(hex: string): string {\n const { r, g, b } = hexToRgb(hex);\n const basicColors: Record<string, RGB> = {\n black: { r: 0, g: 0, b: 0 },\n red: { r: 205, g: 0, b: 0 },\n green: { r: 0, g: 205, b: 0 },\n yellow: { r: 205, g: 205, b: 0 },\n blue: { r: 0, g: 0, b: 238 },\n magenta: { r: 205, g: 0, b: 205 },\n cyan: { r: 0, g: 205, b: 205 },\n white: { r: 229, g: 229, b: 229 },\n };\n\n let nearest = 'white';\n let minDistance = Infinity;\n\n for (const [name, rgb] of Object.entries(basicColors)) {\n const distance = Math.sqrt(\n Math.pow(r - rgb.r, 2) +\n Math.pow(g - rgb.g, 2) +\n Math.pow(b - rgb.b, 2)\n );\n if (distance < minDistance) {\n minDistance = distance;\n nearest = name;\n }\n }\n\n return nearest;\n}\n\nexport function extractGradientColors(gradient: string): string[] {\n const hexMatches = gradient.match(/#[a-fA-F0-9]{6}/g) || [];\n const rgbMatches = gradient.match(/rgba?\\([^)]+\\)/g) || [];\n const namedMatches = gradient.match(/,\\s*([a-z]+)(?:\\s|,|\\))/gi) || [];\n\n const colors: string[] = [\n ...hexMatches,\n ...rgbMatches.map(colorToHex),\n ...namedMatches.map(m => {\n const name = m.replace(/[,\\s)]/g, '').toLowerCase();\n return CSS_NAMED_COLORS[name] || null;\n }).filter((c): c is string => c !== null)\n ];\n\n return colors.length > 0 ? colors : ['#ffffff'];\n}\n\nexport function gradientToSingleColor(gradient: string): string {\n const colors = extractGradientColors(gradient);\n if (colors.length === 0) return '#ffffff';\n if (colors.length === 1) return colors[0] ?? '#ffffff';\n\n const rgbs = colors.map(c => hexToRgb(colorToHex(c)));\n const avgR = Math.round(rgbs.reduce((sum, rgb) => sum + rgb.r, 0) / rgbs.length);\n const avgG = Math.round(rgbs.reduce((sum, rgb) => sum + rgb.g, 0) / rgbs.length);\n const avgB = Math.round(rgbs.reduce((sum, rgb) => sum + rgb.b, 0) / rgbs.length);\n\n return rgbToHex(avgR, avgG, avgB);\n}\n\nexport function cssColorToANSI(\n cssColor: string,\n capability: ColorCapability,\n isBackground: boolean = false\n): string {\n if (capability === 'none') return '';\n\n let resolvedColor: string;\n\n if (cssColor.includes('gradient')) {\n resolvedColor = gradientToSingleColor(cssColor);\n } else {\n resolvedColor = colorToHex(cssColor);\n }\n\n return isBackground\n ? getANSIBackground(resolvedColor, capability)\n : getANSIForeground(resolvedColor, capability);\n}\n\nexport const ANSI = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n italic: '\\x1b[3m',\n underline: '\\x1b[4m',\n blink: '\\x1b[5m',\n inverse: '\\x1b[7m',\n hidden: '\\x1b[8m',\n strikethrough: '\\x1b[9m',\n\n fg: {\n black: '\\x1b[30m',\n red: '\\x1b[31m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n cyan: '\\x1b[36m',\n white: '\\x1b[37m',\n gray: '\\x1b[90m',\n brightRed: '\\x1b[91m',\n brightGreen: '\\x1b[92m',\n brightYellow: '\\x1b[93m',\n brightBlue: '\\x1b[94m',\n brightMagenta: '\\x1b[95m',\n brightCyan: '\\x1b[96m',\n brightWhite: '\\x1b[97m',\n },\n\n bg: {\n black: '\\x1b[40m',\n red: '\\x1b[41m',\n green: '\\x1b[42m',\n yellow: '\\x1b[43m',\n blue: '\\x1b[44m',\n magenta: '\\x1b[45m',\n cyan: '\\x1b[46m',\n white: '\\x1b[47m',\n gray: '\\x1b[100m',\n brightRed: '\\x1b[101m',\n brightGreen: '\\x1b[102m',\n brightYellow: '\\x1b[103m',\n brightBlue: '\\x1b[104m',\n brightMagenta: '\\x1b[105m',\n brightCyan: '\\x1b[106m',\n brightWhite: '\\x1b[107m',\n },\n\n rgb: (r: number, g: number, b: number) => `\\x1b[38;2;${r};${g};${b}m`,\n bgRgb: (r: number, g: number, b: number) => `\\x1b[48;2;${r};${g};${b}m`,\n color256: (n: number) => `\\x1b[38;5;${n}m`,\n bgColor256: (n: number) => `\\x1b[48;5;${n}m`,\n};\n","/**\n * Terminal Formatter - Alignment, key-value, and advanced terminal formatting\n */\n\nimport { getTerminalWidth } from '../utils/environment-detector.js';\nimport { getANSIForeground, getANSIBackground, ANSI, type ColorCapability } from './color-converter.js';\nimport type { ColumnConfig, ColumnAlign, BadgeStyle, TimestampFormat, LogOptions } from '../types/index.js';\n\nexport function stripAnsi(str: string): string {\n return str.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\nexport function getVisibleLength(str: string): number {\n return stripAnsi(str).length;\n}\n\nexport function padToWidth(str: string, width: number, align: ColumnAlign = 'left'): string {\n const visibleLen = getVisibleLength(str);\n if (visibleLen >= width) return str;\n\n const padding = width - visibleLen;\n\n switch (align) {\n case 'right':\n return ' '.repeat(padding) + str;\n case 'center':\n const leftPad = Math.floor(padding / 2);\n const rightPad = padding - leftPad;\n return ' '.repeat(leftPad) + str + ' '.repeat(rightPad);\n case 'left':\n default:\n return str + ' '.repeat(padding);\n }\n}\n\nexport function formatWithRightAlign(\n leftContent: string,\n rightContent: string,\n maxWidth?: number\n): string {\n const width = maxWidth ?? getTerminalWidth();\n const leftLen = getVisibleLength(leftContent);\n const rightLen = getVisibleLength(rightContent);\n\n const gap = width - leftLen - rightLen;\n if (gap <= 1) {\n return `${leftContent} ${rightContent}`;\n }\n\n return `${leftContent}${' '.repeat(gap)}${rightContent}`;\n}\n\nexport function formatColumns(\n columns: ColumnConfig[],\n maxWidth?: number,\n colorCapability: ColorCapability = 'full'\n): string {\n const width = maxWidth ?? getTerminalWidth();\n const totalColumns = columns.length;\n\n const columnsWithWidths = columns.map((col, idx) => {\n if (col.width) return { ...col, calculatedWidth: col.width };\n\n const remainingWidth = width - columns\n .filter((c, i) => i !== idx && c.width)\n .reduce((sum, c) => sum + (c.width ?? 0), 0);\n\n const autoColumns = columns.filter(c => !c.width).length;\n const calculatedWidth = Math.floor(remainingWidth / autoColumns);\n\n return { ...col, calculatedWidth };\n });\n\n return columnsWithWidths.map(col => {\n let content = col.content;\n\n if (col.color && colorCapability !== 'none') {\n const colorCode = getANSIForeground(col.color, colorCapability);\n content = `${colorCode}${content}${ANSI.reset}`;\n }\n\n return padToWidth(content, col.calculatedWidth, col.align);\n }).join('');\n}\n\nexport function formatKeyValue(\n obj: Record<string, unknown>,\n colorCapability: ColorCapability = 'full',\n options: { separator?: string; keyColor?: string; valueColor?: string } = {}\n): string {\n const {\n separator = ' ',\n keyColor = '#888888',\n valueColor = '#00ffff'\n } = options;\n\n const entries = Object.entries(obj);\n if (entries.length === 0) return '';\n\n const keyColorCode = colorCapability !== 'none'\n ? getANSIForeground(keyColor, colorCapability)\n : '';\n const valueColorCode = colorCapability !== 'none'\n ? getANSIForeground(valueColor, colorCapability)\n : '';\n const reset = colorCapability !== 'none' ? ANSI.reset : '';\n\n return entries\n .map(([key, value]) => {\n const valueStr = typeof value === 'object'\n ? JSON.stringify(value)\n : String(value);\n return `${keyColorCode}${key}:${reset} ${valueColorCode}${valueStr}${reset}`;\n })\n .join(separator);\n}\n\nexport function isKeyValueObject(obj: unknown): obj is Record<string, unknown> {\n if (typeof obj !== 'object' || obj === null) return false;\n if (Array.isArray(obj)) return false;\n\n const proto = Object.getPrototypeOf(obj);\n if (proto !== Object.prototype && proto !== null) return false;\n\n const values = Object.values(obj);\n return values.every(v =>\n typeof v === 'string' ||\n typeof v === 'number' ||\n typeof v === 'boolean' ||\n v === null\n );\n}\n\nexport function formatBadge(\n badge: string,\n style: BadgeStyle = 'brackets',\n colorCapability: ColorCapability = 'full',\n color?: string\n): string {\n const reset = colorCapability !== 'none' ? ANSI.reset : '';\n\n const text = badge.toUpperCase();\n\n switch (style) {\n case 'rounded':\n const colorCode1 = color && colorCapability !== 'none' ? getANSIForeground(color, colorCapability) : '';\n const bgBlack1 = colorCapability !== 'none' ? ANSI.bg.black : '';\n return `${bgBlack1}${colorCode1}⟨${text}⟩${reset}`;\n case 'plain':\n const colorCode2 = color && colorCapability !== 'none' ? getANSIForeground(color, colorCapability) : '';\n return `${colorCode2}${text}${reset}`;\n case 'unicode':\n const colorCode3 = color && colorCapability !== 'none' ? getANSIForeground(color, colorCapability) : '';\n const bgBlack3 = colorCapability !== 'none' ? ANSI.bg.black : '';\n return `${bgBlack3}${colorCode3}╭${text}╮${reset}`;\n case 'pill':\n // Badge con background de color y texto blanco/negro\n const bgColor = color && colorCapability !== 'none' ? getANSIBackground(color, colorCapability) : '';\n const fgColor = colorCapability !== 'none' ? getANSIForeground('#000000', colorCapability) : '';\n return `${bgColor}${fgColor}[${text}]${reset}`;\n case 'brackets':\n default:\n const colorCode5 = color && colorCapability !== 'none' ? getANSIForeground(color, colorCapability) : '';\n const bgBlack5 = colorCapability !== 'none' ? ANSI.bg.black : '';\n return `${bgBlack5}${colorCode5}[${text}]${reset}`;\n }\n}\n\nexport function formatTimestamp(\n date: Date = new Date(),\n format: TimestampFormat = 'time'\n): string {\n switch (format) {\n case 'iso':\n return date.toISOString();\n case 'date':\n return date.toISOString().split('T')[0] ?? '';\n case 'time':\n return date.toTimeString().slice(0, 8);\n case 'timeMs':\n return date.toTimeString().slice(0, 8) + '.' +\n String(date.getMilliseconds()).padStart(3, '0');\n case 'relative':\n return formatRelativeTime(date);\n case 'elapsed':\n return formatElapsedTime(date);\n case 'custom':\n default:\n return date.toLocaleTimeString();\n }\n}\n\nlet startTime: number | null = null;\n\nexport function formatRelativeTime(date: Date): string {\n if (startTime === null) {\n startTime = Date.now();\n }\n\n const diff = date.getTime() - startTime;\n\n if (diff < 1000) {\n return `+${diff}ms`;\n } else if (diff < 60000) {\n return `+${(diff / 1000).toFixed(1)}s`;\n } else {\n const mins = Math.floor(diff / 60000);\n const secs = Math.floor((diff % 60000) / 1000);\n return `+${mins}m${secs}s`;\n }\n}\n\nexport function formatElapsedTime(date: Date): string {\n if (startTime === null) {\n startTime = Date.now();\n }\n\n const diff = date.getTime() - startTime;\n const hours = Math.floor(diff / 3600000);\n const mins = Math.floor((diff % 3600000) / 60000);\n const secs = Math.floor((diff % 60000) / 1000);\n\n return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;\n}\n\nexport function resetStartTime(): void {\n startTime = Date.now();\n}\n\nexport function applyLogOptions(\n message: string,\n options: LogOptions,\n colorCapability: ColorCapability = 'full'\n): string {\n let result = message;\n\n if (options.rightAlign) {\n result = formatWithRightAlign(message, options.rightAlign);\n }\n\n return result;\n}\n","/**\n * @fileoverview Step progress renderer for CLI primitives\n */\n\nimport { getANSIForeground, ANSI, type ColorCapability } from '../terminal/color-converter.js';\n\n/**\n * Renderiza un indicador de progreso de step con el formato ` [n/total] msg`,\n * donde el `[n/total]` se emite en cian bold (respetando `colorCap`) para\n * destacarlo del mensaje descriptivo. Pensado para output secuencial de CLI\n * tipo \"steps de un build\", \"fases de un deploy\" o \"tareas de un script\".\n *\n * No hace ningún chequeo de rango sobre `current`/`total` — el caller es\n * responsable de pasar valores coherentes (se renderizan tal cual).\n *\n * @param current - Número de step actual (típicamente 1-based).\n * @param total - Total de steps del proceso.\n * @param msg - Descripción corta del step en curso.\n * @param colorCap - Capacidad de color del terminal destino. Si es `'none'`,\n * el label `[n/total]` se emite sin color.\n * @returns String de una sola línea con formato ` [n/total] msg`.\n *\n * @example\n * ```ts\n * const steps = ['Resolving deps', 'Bundling', 'Writing dist'];\n * steps.forEach((step, i) => {\n * process.stdout.write(renderStep(i + 1, steps.length, step, 'full') + '\\n');\n * });\n * // [1/3] Resolving deps\n * // [2/3] Bundling\n * // [3/3] Writing dist\n * ```\n */\nexport function renderStep(current: number, total: number, msg: string, colorCap: ColorCapability): string {\n const label = `[${current}/${total}]`;\n const colored = colorCap !== 'none'\n ? getANSIForeground('#00bcd4', colorCap) + ANSI.bold + label + ANSI.reset\n : label;\n return ` ${colored} ${msg}`;\n}\n","/**\n * @fileoverview Header renderer for CLI primitives\n */\n\nimport { ANSI } from '../terminal/color-converter.js';\n\n/**\n * Renderiza un header de sección: `title` en bold seguido opcionalmente de\n * `subtitle` en dim (ANSI `2`), ideal para marcar bloques en output de CLI.\n * No usa colores de foreground — sólo atributos de texto, así que el renderer\n * es seguro para cualquier terminal sin importar la paleta del theme activo.\n *\n * @param title - Texto principal del header (siempre en bold).\n * @param subtitle - Texto secundario a la derecha del título; se renderiza\n * dimmed y separado por un espacio. Omitir si no aplica.\n * @returns String de una línea con formato ` <bold>title</bold> <dim>subtitle</dim>`.\n *\n * @example\n * ```ts\n * process.stdout.write(renderHeader('Deploy', 'production · us-east-1') + '\\n');\n * // **Deploy** production · us-east-1 (con atributos ANSI aplicados)\n * ```\n *\n * @example\n * ```ts\n * // Header sin subtítulo\n * process.stdout.write(renderHeader('Build summary') + '\\n');\n * ```\n */\nexport function renderHeader(title: string, subtitle?: string): string {\n const t = ANSI.bold + title + ANSI.reset;\n const s = subtitle ? ANSI.dim + ` ${subtitle}` + ANSI.reset : '';\n return ` ${t}${s}`;\n}\n","/**\n * @fileoverview Divider renderer for CLI primitives\n */\n\nimport { ANSI } from '../terminal/color-converter.js';\nimport { getTerminalWidth } from '../utils/environment-detector.js';\n\n/**\n * Renderiza una línea divisoria horizontal dimmed (ANSI `2`) usando el\n * caracter `─`. Por defecto el ancho es `min(terminalWidth - 4, 60)` para\n * no ocupar todo el ancho de ventana y quedar visualmente alineado con otros\n * primitives (box, header, table) que dejan 2 espacios de indentación.\n *\n * @param width - Ancho explícito en columnas visibles. Si se omite, se calcula\n * automáticamente a partir del ancho del terminal (capped a 60).\n * @returns String de una línea con `width` caracteres `─` envueltos en ANSI dim.\n *\n * @example\n * ```ts\n * // Divider automático (respeta el ancho del terminal)\n * process.stdout.write(renderDivider() + '\\n');\n * ```\n *\n * @example\n * ```ts\n * // Divider de ancho fijo para alinear con otra salida\n * process.stdout.write(renderDivider(40) + '\\n');\n * ```\n *\n * @see {@link getTerminalWidth} para la detección de ancho cuando `width` se omite.\n */\nexport function renderDivider(width?: number): string {\n const w = width ?? Math.min(getTerminalWidth() - 4, 60);\n return ANSI.dim + ' ' + '\\u2500'.repeat(w) + ANSI.reset;\n}\n","/**\n * @fileoverview Box renderer for CLI primitives\n */\n\nimport type { IBoxOptions } from '../types/core.js';\nimport type { ColorCapability } from '../terminal/color-converter.js';\nimport { getANSIForeground, ANSI } from '../terminal/color-converter.js';\nimport { getTerminalWidth } from '../utils/environment-detector.js';\nimport { stripAnsi, getVisibleLength } from '../terminal/formatter.js';\n\n/**\n * Mapa de juegos de caracteres Unicode para los 4 estilos de borde soportados\n * por {@link renderBox}. Cada entrada expone las 4 esquinas (`tl`, `tr`, `bl`,\n * `br`), el caracter horizontal (`h`) y el vertical (`v`) que componen el marco.\n *\n * - `single`: l\\u00edneas finas (U+2500 / U+2502).\n * - `rounded`: igual que `single` con esquinas redondeadas.\n * - `double`: l\\u00edneas dobles (U+2550 / U+2551), alto contraste visual.\n * - `bold`: l\\u00edneas gruesas (U+2501 / U+2503), para destacar bloques cr\\u00edticos.\n *\n * @internal Lookup interno del renderer; no es API p\\u00fablica.\n */\nconst BORDER_CHARS = {\n single: { tl: '\\u250c', tr: '\\u2510', bl: '\\u2514', br: '\\u2518', h: '\\u2500', v: '\\u2502' },\n rounded: { tl: '\\u256d', tr: '\\u256e', bl: '\\u2570', br: '\\u256f', h: '\\u2500', v: '\\u2502' },\n double: { tl: '\\u2554', tr: '\\u2557', bl: '\\u255a', br: '\\u255d', h: '\\u2550', v: '\\u2551' },\n bold: { tl: '\\u250f', tr: '\\u2513', bl: '\\u2517', br: '\\u251b', h: '\\u2501', v: '\\u2503' },\n} as const;\n\n/**\n * Renderiza `content` envuelto en un box con borde Unicode, respetando el\n * ancho del terminal. El ancho interno se calcula a partir de la l\\u00ednea m\\u00e1s\n * larga (o del {@link IBoxOptions.title} si es m\\u00e1s ancho) y se acota a\n * `min(terminalWidth - 4, 80)` columnas para no romper layouts estrechos.\n *\n * El padding se aplica como l\\u00edneas vac\\u00edas sim\\u00e9tricas arriba/abajo del\n * contenido. Si `borderColor` se omite o `colorCap` es `'none'`, el borde se\n * emite sin secuencias ANSI (output plain-text seguro para logs y pipes).\n *\n * @param content - Texto a envolver; puede contener m\\u00faltiples l\\u00edneas (`\\n`) y\n * secuencias ANSI embebidas \\u2014 el c\\u00e1lculo de ancho usa el largo visible.\n * @param options - Configuraci\\u00f3n del box (title, borderColor, borderStyle,\n * padding). Ver {@link IBoxOptions}.\n * @param colorCap - Capacidad de color del terminal destino. Si es `'none'`,\n * se omite cualquier secuencia ANSI.\n * @returns String multilinea con el box ya construido (sin trailing newline).\n *\n * @example\n * ```ts\n * // Box b\\u00e1sico con borde redondeado (default)\n * process.stdout.write(renderBox('Deploy completado') + '\\n');\n * ```\n *\n * @example\n * ```ts\n * // Box con t\\u00edtulo embebido en el borde superior y color custom\n * process.stdout.write(renderBox('Service: auth-svc\\nStatus: healthy', {\n * title: 'Health Check',\n * borderColor: '#00bcd4',\n * borderStyle: 'double',\n * padding: 1\n * }) + '\\n');\n * ```\n *\n * @see {@link IBoxOptions} para el detalle de cada opci\\u00f3n.\n * @see {@link getTerminalWidth} para la detecci\\u00f3n de ancho.\n */\nexport function renderBox(content: string, options: IBoxOptions = {}, colorCap: ColorCapability = 'full'): string {\n const {\n title,\n borderColor,\n borderStyle = 'rounded',\n padding = 0,\n } = options;\n\n const chars = BORDER_CHARS[borderStyle] ?? BORDER_CHARS.rounded;\n const lines = content.split('\\n');\n const maxTermWidth = Math.min(getTerminalWidth() - 4, 80);\n\n // Calculate content width from visible text\n const contentWidths = lines.map(l => getVisibleLength(l));\n const titleWidth = title ? stripAnsi(title).length + 2 : 0; // +2 for spaces around title\n const maxContentWidth = Math.max(...contentWidths, titleWidth);\n const innerWidth = Math.min(maxContentWidth + 2, maxTermWidth); // +2 for horizontal padding\n\n // Color wrapper for border chars\n const bc = borderColor && colorCap !== 'none'\n ? getANSIForeground(borderColor, colorCap)\n : '';\n const reset = bc ? ANSI.reset : '';\n\n const wrap = (char: string) => `${bc}${char}${reset}`;\n\n // Build top border (with optional title)\n let topBorder: string;\n if (title) {\n const titleStr = ` ${title} `;\n const afterTitle = innerWidth - stripAnsi(titleStr).length;\n topBorder = ` ${wrap(chars.tl)}${wrap(chars.h)}${wrap(titleStr)}${wrap(chars.h.repeat(Math.max(0, afterTitle - 1)))}${wrap(chars.tr)}`;\n } else {\n topBorder = ` ${wrap(chars.tl)}${wrap(chars.h.repeat(innerWidth))}${wrap(chars.tr)}`;\n }\n\n // Build bottom border\n const bottomBorder = ` ${wrap(chars.bl)}${wrap(chars.h.repeat(innerWidth))}${wrap(chars.br)}`;\n\n // Build padding lines\n const emptyLine = ` ${wrap(chars.v)}${' '.repeat(innerWidth)}${wrap(chars.v)}`;\n const paddingLines = padding > 0 ? Array(padding).fill(emptyLine) : [];\n\n // Build content lines\n const contentLines = lines.map(line => {\n const visible = getVisibleLength(line);\n const pad = innerWidth - visible - 1; // -1 for left space\n return ` ${wrap(chars.v)} ${line}${' '.repeat(Math.max(0, pad))}${wrap(chars.v)}`;\n });\n\n return [\n topBorder,\n ...paddingLines,\n ...contentLines,\n ...paddingLines,\n bottomBorder,\n ].join('\\n');\n}\n","/**\n * @fileoverview CLI table renderer for CLI primitives\n */\n\nimport type { ITableOptions } from '../types/core.js';\nimport type { ColorCapability } from '../terminal/color-converter.js';\nimport { getANSIForeground, ANSI } from '../terminal/color-converter.js';\nimport { getVisibleLength, padToWidth } from '../terminal/formatter.js';\n\n/**\n * Renderiza un array de objetos como tabla ASCII alineada, con headers en\n * cian bold y separador (`─`) bajo la cabecera. Las columnas se autodetectan\n * a partir de las keys del primer row salvo que `options.columns` las imponga,\n * y los labels se toman de `options.head` (default: nombres de columna).\n *\n * El ancho de cada columna se calcula como `max(header, valor más largo) + 2`\n * para garantizar padding horizontal consistente. Si `colorCap` es `'none'`,\n * se omiten todas las secuencias ANSI (útil para logs plain-text o CI).\n *\n * @param rows - Array de row objects. Un array vacío devuelve string vacío.\n * @param options - Ver {@link ITableOptions} para `columns` y `head`.\n * @param colorCap - Capacidad de color del terminal destino.\n * @returns String multilinea con la tabla (header + separator + data rows),\n * o `''` si `rows` está vacío.\n *\n * @example\n * ```ts\n * // Auto-detect columnas desde las keys del primer row\n * const rows = [\n * { service: 'auth', status: 'healthy', latency: 12 },\n * { service: 'api', status: 'degraded', latency: 245 }\n * ];\n * process.stdout.write(renderTable(rows) + '\\n');\n * // ┌─────────┬──────────┬─────────┐\n * // │ service │ status │ latency │\n * // ─────────────────────────────────\n * // │ auth │ healthy │ 12 │\n * // │ api │ degraded │ 245 │\n * ```\n *\n * @example\n * ```ts\n * // Forzar columnas y renombrar headers\n * process.stdout.write(renderTable(rows, {\n * columns: ['service', 'latency'],\n * head: ['Service', 'Latency (ms)']\n * }, 'none') + '\\n');\n * ```\n *\n * @see {@link ITableOptions} para las opciones disponibles.\n * @see {@link getVisibleLength} y {@link padToWidth} para el cálculo de ancho.\n */\nexport function renderTable(\n rows: Record<string, unknown>[],\n options: ITableOptions = {},\n colorCap: ColorCapability = 'full'\n): string {\n if (rows.length === 0) return '';\n\n // Determine columns from options or first row's keys\n const columns = options.columns ?? Object.keys(rows[0]!);\n const headers = options.head ?? columns;\n\n // Calculate column widths (max of header and all values)\n const colWidths = columns.map((col, i) => {\n const headerLen = getVisibleLength(headers[i] ?? col);\n const maxValueLen = rows.reduce((max, row) => {\n const val = String(row[col] ?? '');\n return Math.max(max, getVisibleLength(val));\n }, 0);\n return Math.max(headerLen, maxValueLen) + 2; // +2 for padding\n });\n\n // Color helpers\n const cyan = colorCap !== 'none' ? getANSIForeground('#00bcd4', colorCap) : '';\n const dim = colorCap !== 'none' ? ANSI.dim : '';\n const reset = colorCap !== 'none' ? ANSI.reset : '';\n\n // Build header row\n const headerRow = ' ' + columns.map((col, i) => {\n const label = headers[i] ?? col;\n return cyan + ANSI.bold + padToWidth(` ${label}`, colWidths[i]!) + reset;\n }).join('');\n\n // Build separator\n const separator = ' ' + dim + colWidths.map(w => '\\u2500'.repeat(w)).join('\\u2500') + reset;\n\n // Build data rows\n const dataRows = rows.map(row => {\n return ' ' + columns.map((col, i) => {\n const val = String(row[col] ?? '');\n return padToWidth(` ${val}`, colWidths[i]!);\n }).join('');\n });\n\n return [headerRow, separator, ...dataRows].join('\\n');\n}\n","/**\n * @fileoverview Built-in spinner implementation for CLI primitives.\n *\n * Expone dos implementaciones de {@link ISpinnerHandle}:\n * - {@link SpinnerManager}: spinner braille animado para TTY interactiva.\n * - {@link NoopSpinner}: fallback sin animaci\\u00f3n para non-TTY / silent mode.\n *\n * La factor\\u00eda que decide cu\\u00e1l instanciar vive en `TerminalBridge.spinner()`;\n * los consumers rara vez construyen estas clases directamente.\n */\n\nimport type { ISpinnerHandle, LoggerConfig } from '../types/core.js';\nimport type { Logger } from '../Logger.js';\nimport { ANSI } from '../terminal/color-converter.js';\n\n/**\n * Frames braille usados por la animaci\\u00f3n del spinner. Cada frame es un\n * car\\u00e1cter del bloque Unicode Braille Patterns (U+2800\\u2013U+28FF) que da la\n * ilusi\\u00f3n de rotaci\\u00f3n al ciclarlos a ~12 FPS. Elegidos sobre caracteres\n * ASCII (`|/-\\`) porque renderizan m\\u00e1s suaves en terminales modernas.\n */\nconst SPINNER_FRAMES = ['\\u280b', '\\u2819', '\\u2839', '\\u2838', '\\u283c', '\\u2834', '\\u2826', '\\u2827', '\\u2807', '\\u280f'];\n\n/**\n * Intervalo entre frames del spinner en milisegundos. 80 ms \\u2248 12.5 FPS:\n * suficientemente r\\u00e1pido para sentirse responsivo sin consumir CPU\n * perceptiblemente en runs largos.\n */\nconst FRAME_INTERVAL = 80;\n\n/**\n * Spinner interactivo para TTY: cicla frames braille reescribiendo la l\\u00ednea\n * actual en su sitio (no emite l\\u00edneas nuevas hasta el stop).\n *\n * Para no poluir stdout piped ni entrelazarse con el output normal del\n * {@link Logger}, hace dos cosas no obvias:\n * 1. Escribe SIEMPRE a `process.stderr` (carriage return + `\\x1b[K` para\n * limpiar la l\\u00ednea antes de cada render).\n * 2. Con `start()` mutea el logger (`outputMode: 'silent'`) y lo restaura a\n * `'console'` en cualquier m\\u00e9todo de finalizaci\\u00f3n (`stop`/`succeed`/`fail`).\n * Sin esto, los logs del usuario se imprimir\\u00edan encima del frame animado.\n *\n * No gestiona TTY detection \\u2014 quien lo instancia (`TerminalBridge`) ya valid\\u00f3\n * que hay TTY. Para non-TTY ver {@link NoopSpinner}.\n *\n * @implements {ISpinnerHandle}\n *\n * @example\n * ```ts\n * const spinner = new SpinnerManager('Compilando...', logger.config, logger);\n * spinner.start();\n * // ...trabajo as\\u00edncrono...\n * spinner.succeed('Build OK');\n * // stderr: \" \\u2713 Build OK\"\n * ```\n *\n * @see {@link NoopSpinner} para el path non-TTY.\n * @see {@link ISpinnerHandle} para el contrato de la API p\\u00fablica.\n */\nexport class SpinnerManager implements ISpinnerHandle {\n private message: string;\n private frameIndex = 0;\n private interval: ReturnType<typeof setInterval> | null = null;\n private _logger: Logger;\n\n /**\n * @param {string} message - Texto a mostrar al lado del frame animado.\n * Mutables luego v\\u00eda {@link SpinnerManager.text}.\n * @param {LoggerConfig} _config - Reservado para configuraci\\u00f3n futura;\n * actualmente no se lee dentro de la clase (lo conserva solo el caller).\n * @param {Logger} logger - Instancia del logger due\\u00f1a del spinner. Se\n * mutea/restaura con `updateConfig({ outputMode })` en start/stop.\n */\n constructor(message: string, _config: LoggerConfig, logger: Logger) {\n this.message = message;\n this._logger = logger;\n }\n\n /**\n * Arranca la animaci\\u00f3n. Idempotente: si ya est\\u00e1 corriendo, no hace nada.\n *\n * Como efecto lateral mutea el logger pasado al constructor cambiando su\n * `outputMode` a `'silent'` \\u2014 cualquier log durante la animaci\\u00f3n quedar\\u00eda\n * bufferizado y se descarta al restaurar el modo. Llama siempre a\n * {@link stop}, {@link succeed} o {@link fail} para restaurar el output.\n *\n * @returns {void}\n */\n start(): void {\n if (this.interval) return; // Already running\n\n // Switch logger to buffer mode to prevent garbled output\n this._logger.updateConfig({ outputMode: 'silent' });\n\n this.frameIndex = 0;\n this.render();\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;\n this.render();\n }, FRAME_INTERVAL);\n }\n\n /**\n * Detiene la animaci\\u00f3n y limpia la l\\u00ednea, sin emitir mensaje de estado.\n * Restaura el `outputMode` del logger a `'console'`.\n *\n * \\u00datil cuando el caller ya emiti\\u00f3 su propio output final y solo necesita\n * desmontar el spinner. Para terminaci\\u00f3n con tick/cross usa\n * {@link succeed} / {@link fail}.\n *\n * @returns {void}\n */\n stop(): void {\n this.clearInterval();\n this.clearLine();\n // Restore logger output\n this._logger.updateConfig({ outputMode: 'console' });\n }\n\n /**\n * Detiene la animaci\\u00f3n y emite el mensaje con un check verde (`\\u2713`).\n * Restaura el `outputMode` del logger a `'console'`.\n *\n * @param {string} [msg] - Texto final a mostrar. Si se omite, reutiliza\n * el `message` con el que se construy\\u00f3 el spinner (o el \\u00faltimo seteado\n * v\\u00eda {@link text}).\n * @returns {void}\n *\n * @example\n * ```ts\n * spinner.succeed(); // \\u2192 \" \\u2713 <message inicial>\"\n * spinner.succeed('Hecho'); // \\u2192 \" \\u2713 Hecho\"\n * ```\n */\n succeed(msg?: string): void {\n this.clearInterval();\n this.clearLine();\n const text = msg ?? this.message;\n process.stderr.write(` ${ANSI.fg.green}\\u2713${ANSI.reset} ${text}\\n`);\n this._logger.updateConfig({ outputMode: 'console' });\n }\n\n /**\n * Detiene la animaci\\u00f3n y emite el mensaje con una cruz roja (`\\u2717`).\n * Restaura el `outputMode` del logger a `'console'`.\n *\n * @param {string} [msg] - Texto final a mostrar. Si se omite, reutiliza\n * el `message` con el que se construy\\u00f3 el spinner (o el \\u00faltimo seteado\n * v\\u00eda {@link text}).\n * @returns {void}\n *\n * @example\n * ```ts\n * try {\n * await build();\n * spinner.succeed('Build OK');\n * } catch (e) {\n * spinner.fail(`Build fallido: ${e.message}`);\n * }\n * ```\n */\n fail(msg?: string): void {\n this.clearInterval();\n this.clearLine();\n const text = msg ?? this.message;\n process.stderr.write(` ${ANSI.fg.red}\\u2717${ANSI.reset} ${text}\\n`);\n this._logger.updateConfig({ outputMode: 'console' });\n }\n\n /**\n * Reemplaza el texto mostrado al lado del frame sin reiniciar la animaci\\u00f3n\n * ni perder el frame actual. Pensado para actualizar progreso in-place\n * (p.ej. contador de items procesados).\n *\n * @param {string} msg - Nuevo texto a mostrar.\n * @returns {void}\n */\n text(msg: string): void {\n this.message = msg;\n }\n\n private render(): void {\n const frame = SPINNER_FRAMES[this.frameIndex] ?? SPINNER_FRAMES[0];\n const line = ` ${ANSI.fg.cyan}${frame}${ANSI.reset} ${this.message}`;\n process.stderr.write(`\\r\\x1b[K${line}`);\n }\n\n private clearLine(): void {\n process.stderr.write('\\r\\x1b[K');\n }\n\n private clearInterval(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n}\n\n/**\n * Spinner degenerate para non-TTY (CI logs, pipes, `outputMode: 'silent'`).\n *\n * No anima nada: traduce los eventos del ciclo de vida del spinner a llamadas\n * normales del logger (`info` en start, `success`/`error` en finish). Así el\n * consumidor mantiene la misma API {@link ISpinnerHandle} sin saber si está\n * corriendo en terminal interactiva o en un job de CI.\n *\n * A diferencia de {@link SpinnerManager}, **no** toca el `outputMode` del\n * logger — no hay nada que mutear porque no hay frame animado que proteger.\n *\n * @implements {ISpinnerHandle}\n *\n * @example\n * ```ts\n * // En CI (sin TTY) el TerminalBridge entrega un NoopSpinner automáticamente:\n * const s = logger.spinner('Running tests...');\n * s.start(); // logger.info('Running tests...')\n * s.succeed('All green'); // logger.success('All green')\n * ```\n *\n * @see {@link SpinnerManager} para el path interactivo con animación.\n */\nexport class NoopSpinner implements ISpinnerHandle {\n private message: string;\n private _logger: Logger;\n\n /**\n * @param {string} message - Texto base; se reutiliza como mensaje final\n * si {@link succeed} / {@link fail} se llaman sin argumento.\n * @param {Logger} logger - Logger sobre el que se emiten los eventos.\n */\n constructor(message: string, logger: Logger) {\n this.message = message;\n this._logger = logger;\n }\n\n /**\n * Emite el mensaje inicial como `logger.info(...)`. No arranca ningún\n * timer — en non-TTY no hay nada que animar.\n *\n * @returns {void}\n */\n start(): void {\n this._logger.info(this.message);\n }\n\n /**\n * No-op — no hay animación que detener ni output que restaurar.\n *\n * @returns {void}\n */\n stop(): void {\n // No-op\n }\n\n /**\n * Emite el mensaje final como `logger.success(...)`.\n *\n * @param {string} [msg] - Texto final; si se omite usa el `message`\n * inicial o el último seteado vía {@link text}.\n * @returns {void}\n */\n succeed(msg?: string): void {\n this._logger.success(msg ?? this.message);\n }\n\n /**\n * Emite el mensaje final como `logger.error(...)`.\n *\n * @param {string} [msg] - Texto final; si se omite usa el `message`\n * inicial o el último seteado vía {@link text}.\n * @returns {void}\n */\n fail(msg?: string): void {\n this._logger.error(msg ?? this.message);\n }\n\n /**\n * Actualiza el mensaje interno (sin output). Solo afecta al texto que\n * emitirán {@link succeed} / {@link fail} cuando se invoquen sin argumento.\n *\n * @param {string} msg - Nuevo texto base.\n * @returns {void}\n */\n text(msg: string): void {\n this.message = msg;\n }\n}\n"],"mappings":"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"}