@mks2508/better-logger 3.1.0 → 5.0.0

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 (106) hide show
  1. package/CHANGELOG.json +45 -1
  2. package/dist/Logger.d.ts +129 -4
  3. package/dist/Logger.d.ts.map +1 -1
  4. package/dist/ScopedLogger.d.ts +17 -0
  5. package/dist/ScopedLogger.d.ts.map +1 -1
  6. package/dist/chunks/{Logger-C086w3EM.js → Logger-BZ7B7OXE.js} +258 -16
  7. package/dist/chunks/Logger-BZ7B7OXE.js.map +1 -0
  8. package/dist/chunks/Logger-Cbi1f10o.js +2 -0
  9. package/dist/chunks/Logger-Cbi1f10o.js.map +1 -0
  10. package/dist/chunks/cli-module-CadqgZ1Z.js +2 -0
  11. package/dist/chunks/cli-module-CadqgZ1Z.js.map +1 -0
  12. package/dist/chunks/cli-module-ClIJmaT8.js +383 -0
  13. package/dist/chunks/cli-module-ClIJmaT8.js.map +1 -0
  14. package/dist/chunks/color-converter-CCSQRztd.js +2 -0
  15. package/dist/chunks/color-converter-CCSQRztd.js.map +1 -0
  16. package/dist/chunks/color-converter-_Xdmsy7E.js +462 -0
  17. package/dist/chunks/color-converter-_Xdmsy7E.js.map +1 -0
  18. package/dist/chunks/{environment-DXHouGD4.js → environment-C1xxvc8l.js} +28 -478
  19. package/dist/chunks/environment-C1xxvc8l.js.map +1 -0
  20. package/dist/chunks/environment-Cprkw3g9.js +4 -0
  21. package/dist/chunks/environment-Cprkw3g9.js.map +1 -0
  22. package/dist/chunks/{formatting-BNnVUPcw.js → formatting-DMJxYq9o.js} +18 -18
  23. package/dist/chunks/{formatting-BNnVUPcw.js.map → formatting-DMJxYq9o.js.map} +1 -1
  24. package/dist/chunks/{formatting-Cg5YhB9Y.js → formatting-DpKxCsXq.js} +2 -2
  25. package/dist/chunks/{formatting-Cg5YhB9Y.js.map → formatting-DpKxCsXq.js.map} +1 -1
  26. package/dist/cli-module.d.ts +15 -0
  27. package/dist/cli-module.d.ts.map +1 -0
  28. package/dist/cli-primitives/box.d.ts +11 -0
  29. package/dist/cli-primitives/box.d.ts.map +1 -0
  30. package/dist/cli-primitives/cli-table.d.ts +11 -0
  31. package/dist/cli-primitives/cli-table.d.ts.map +1 -0
  32. package/dist/cli-primitives/divider.d.ts +11 -0
  33. package/dist/cli-primitives/divider.d.ts.map +1 -0
  34. package/dist/cli-primitives/header.d.ts +12 -0
  35. package/dist/cli-primitives/header.d.ts.map +1 -0
  36. package/dist/cli-primitives/index.d.ts +13 -0
  37. package/dist/cli-primitives/index.d.ts.map +1 -0
  38. package/dist/cli-primitives/server-fallback.d.ts +25 -0
  39. package/dist/cli-primitives/server-fallback.d.ts.map +1 -0
  40. package/dist/cli-primitives/spinner.d.ts +47 -0
  41. package/dist/cli-primitives/spinner.d.ts.map +1 -0
  42. package/dist/cli-primitives/step.d.ts +11 -0
  43. package/dist/cli-primitives/step.d.ts.map +1 -0
  44. package/dist/cli.cjs +2 -0
  45. package/dist/cli.cjs.map +1 -0
  46. package/dist/cli.js +12 -0
  47. package/dist/cli.js.map +1 -0
  48. package/dist/constants.d.ts +9 -1
  49. package/dist/constants.d.ts.map +1 -1
  50. package/dist/core.cjs +1 -1
  51. package/dist/core.js +2 -2
  52. package/dist/exports-module.d.ts +1 -1
  53. package/dist/exports-module.d.ts.map +1 -1
  54. package/dist/exports.cjs +1 -1
  55. package/dist/exports.js +2 -2
  56. package/dist/index.cjs +1 -1
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.ts +13 -3
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +162 -195
  61. package/dist/index.js.map +1 -1
  62. package/dist/styling-module.d.ts +1 -1
  63. package/dist/styling-module.d.ts.map +1 -1
  64. package/dist/styling.cjs +1 -1
  65. package/dist/styling.js +3 -3
  66. package/dist/types/core.d.ts +91 -0
  67. package/dist/types/core.d.ts.map +1 -1
  68. package/dist/types/index.d.ts +1 -1
  69. package/dist/types/index.d.ts.map +1 -1
  70. package/dist/writers/BufferWriter.d.ts +96 -0
  71. package/dist/writers/BufferWriter.d.ts.map +1 -0
  72. package/dist/writers/index.d.ts +6 -0
  73. package/dist/writers/index.d.ts.map +1 -0
  74. package/package.json +28 -3
  75. package/packages/core/package.json +1 -1
  76. package/playground/demo-all.ts +95 -0
  77. package/playground/demo-box.ts +85 -0
  78. package/playground/demo-levels.ts +56 -0
  79. package/playground/demo-real-world.ts +98 -0
  80. package/playground/demo-spinner.ts +77 -0
  81. package/playground/demo-steps.ts +72 -0
  82. package/playground/demo-table.ts +83 -0
  83. package/src/Logger.ts +263 -16
  84. package/src/ScopedLogger.ts +43 -1
  85. package/src/cli-module.ts +21 -0
  86. package/src/cli-primitives/box.ts +86 -0
  87. package/src/cli-primitives/cli-table.ts +62 -0
  88. package/src/cli-primitives/divider.ts +17 -0
  89. package/src/cli-primitives/header.ts +18 -0
  90. package/src/cli-primitives/index.ts +13 -0
  91. package/src/cli-primitives/server-fallback.ts +54 -0
  92. package/src/cli-primitives/spinner.ts +133 -0
  93. package/src/cli-primitives/step.ts +22 -0
  94. package/src/constants.ts +14 -2
  95. package/src/index.ts +23 -2
  96. package/src/types/core.ts +99 -0
  97. package/src/types/index.ts +4 -0
  98. package/src/writers/BufferWriter.ts +157 -0
  99. package/src/writers/index.ts +6 -0
  100. package/vite.config.ts +33 -0
  101. package/dist/chunks/Logger-BV0v1AyC.js +0 -2
  102. package/dist/chunks/Logger-BV0v1AyC.js.map +0 -1
  103. package/dist/chunks/Logger-C086w3EM.js.map +0 -1
  104. package/dist/chunks/environment-C_8J-zQ_.js +0 -4
  105. package/dist/chunks/environment-C_8J-zQ_.js.map +0 -1
  106. package/dist/chunks/environment-DXHouGD4.js.map +0 -1
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @fileoverview Built-in spinner implementation for CLI primitives
3
+ * @since 5.0.0
4
+ */
5
+
6
+ import type { ISpinnerHandle, LoggerConfig } from '../types/core.js';
7
+ import type { Logger } from '../Logger.js';
8
+ import { ANSI } from '../terminal/color-converter.js';
9
+
10
+ /** Braille-based spinner animation frames */
11
+ const SPINNER_FRAMES = ['\u280b', '\u2819', '\u2839', '\u2838', '\u283c', '\u2834', '\u2826', '\u2827', '\u2807', '\u280f'];
12
+
13
+ /** Spinner frame interval in milliseconds */
14
+ const FRAME_INTERVAL = 80;
15
+
16
+ /**
17
+ * Interactive terminal spinner with in-place line updates.
18
+ * Writes to stderr to avoid polluting piped stdout.
19
+ *
20
+ * @implements {ISpinnerHandle}
21
+ * @since 5.0.0
22
+ */
23
+ export class SpinnerManager implements ISpinnerHandle {
24
+ private message: string;
25
+ private frameIndex = 0;
26
+ private interval: ReturnType<typeof setInterval> | null = null;
27
+ private _logger: Logger;
28
+
29
+ constructor(message: string, _config: LoggerConfig, logger: Logger) {
30
+ this.message = message;
31
+ this._logger = logger;
32
+ }
33
+
34
+ /** Start the spinner animation */
35
+ start(): void {
36
+ if (this.interval) return; // Already running
37
+
38
+ // Switch logger to buffer mode to prevent garbled output
39
+ this._logger.updateConfig({ outputMode: 'silent' });
40
+
41
+ this.frameIndex = 0;
42
+ this.render();
43
+ this.interval = setInterval(() => {
44
+ this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;
45
+ this.render();
46
+ }, FRAME_INTERVAL);
47
+ }
48
+
49
+ /** Stop the spinner without a status message */
50
+ stop(): void {
51
+ this.clearInterval();
52
+ this.clearLine();
53
+ // Restore logger output
54
+ this._logger.updateConfig({ outputMode: 'console' });
55
+ }
56
+
57
+ /** Stop with a success indicator */
58
+ succeed(msg?: string): void {
59
+ this.clearInterval();
60
+ this.clearLine();
61
+ const text = msg ?? this.message;
62
+ process.stderr.write(` ${ANSI.fg.green}\u2713${ANSI.reset} ${text}\n`);
63
+ this._logger.updateConfig({ outputMode: 'console' });
64
+ }
65
+
66
+ /** Stop with a failure indicator */
67
+ fail(msg?: string): void {
68
+ this.clearInterval();
69
+ this.clearLine();
70
+ const text = msg ?? this.message;
71
+ process.stderr.write(` ${ANSI.fg.red}\u2717${ANSI.reset} ${text}\n`);
72
+ this._logger.updateConfig({ outputMode: 'console' });
73
+ }
74
+
75
+ /** Update the spinner text while running */
76
+ text(msg: string): void {
77
+ this.message = msg;
78
+ }
79
+
80
+ private render(): void {
81
+ const frame = SPINNER_FRAMES[this.frameIndex] ?? SPINNER_FRAMES[0];
82
+ const line = ` ${ANSI.fg.cyan}${frame}${ANSI.reset} ${this.message}`;
83
+ process.stderr.write(`\r\x1b[K${line}`);
84
+ }
85
+
86
+ private clearLine(): void {
87
+ process.stderr.write('\r\x1b[K');
88
+ }
89
+
90
+ private clearInterval(): void {
91
+ if (this.interval) {
92
+ clearInterval(this.interval);
93
+ this.interval = null;
94
+ }
95
+ }
96
+ }
97
+
98
+ /**
99
+ * No-op spinner for non-TTY environments or silent mode.
100
+ * Logs start/succeed/fail as plain log messages.
101
+ *
102
+ * @implements {ISpinnerHandle}
103
+ * @since 5.0.0
104
+ */
105
+ export class NoopSpinner implements ISpinnerHandle {
106
+ private message: string;
107
+ private _logger: Logger;
108
+
109
+ constructor(message: string, logger: Logger) {
110
+ this.message = message;
111
+ this._logger = logger;
112
+ }
113
+
114
+ start(): void {
115
+ this._logger.info(this.message);
116
+ }
117
+
118
+ stop(): void {
119
+ // No-op
120
+ }
121
+
122
+ succeed(msg?: string): void {
123
+ this._logger.success(msg ?? this.message);
124
+ }
125
+
126
+ fail(msg?: string): void {
127
+ this._logger.error(msg ?? this.message);
128
+ }
129
+
130
+ text(msg: string): void {
131
+ this.message = msg;
132
+ }
133
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @fileoverview Step progress renderer for CLI primitives
3
+ * @since 5.0.0
4
+ */
5
+
6
+ import { getANSIForeground, ANSI, type ColorCapability } from '../terminal/color-converter.js';
7
+
8
+ /**
9
+ * Renders a step progress indicator like ` [2/5] Analyzing repository...`
10
+ * @param current - Current step number
11
+ * @param total - Total number of steps
12
+ * @param msg - Step description message
13
+ * @param colorCap - Terminal color capability
14
+ * @returns Formatted step string
15
+ */
16
+ export function renderStep(current: number, total: number, msg: string, colorCap: ColorCapability): string {
17
+ const label = `[${current}/${total}]`;
18
+ const colored = colorCap !== 'none'
19
+ ? getANSIForeground('#00bcd4', colorCap) + ANSI.bold + label + ANSI.reset
20
+ : label;
21
+ return ` ${colored} ${msg}`;
22
+ }
package/src/constants.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Global constants for Advanced Logger
3
3
  */
4
4
 
5
- import type { LogLevel, AdaptiveColors } from './types/index.js';
5
+ import type { LogLevel, AdaptiveColors, CLILogLevel, Verbosity } from './types/index.js';
6
6
  import type { LevelStyleConfig } from './utils/index.js';
7
7
 
8
8
  /**
@@ -298,4 +298,16 @@ export function getOptimalConfig() {
298
298
  ...DEFAULT_CONFIG,
299
299
  ...BUILD_PRESETS[preset]
300
300
  };
301
- }
301
+ }
302
+
303
+ /**
304
+ * CLI log level to internal verbosity mapping
305
+ * @since 5.0.0
306
+ */
307
+ export const CLI_LEVEL_MAP: Record<CLILogLevel, { verbosity: Verbosity; showPrimitives: boolean }> = {
308
+ silent: { verbosity: 'silent', showPrimitives: false },
309
+ quiet: { verbosity: 'error', showPrimitives: false },
310
+ normal: { verbosity: 'info', showPrimitives: true },
311
+ verbose: { verbosity: 'debug', showPrimitives: true },
312
+ debug: { verbosity: 'debug', showPrimitives: true },
313
+ } as const;
package/src/index.ts CHANGED
@@ -18,7 +18,10 @@ import type {
18
18
  ThemeVariant,
19
19
  BannerType,
20
20
  StyleOptions,
21
- ILogHandler
21
+ ILogHandler,
22
+ CLILogLevel,
23
+ IBoxOptions,
24
+ ITableOptions,
22
25
  } from './types/index.js';
23
26
 
24
27
  // Lazy singleton - se inicializa solo cuando se necesita
@@ -115,6 +118,16 @@ export const logAnimated = (message: string, duration?: number) =>
115
118
  getLogger().logAnimated(message, duration);
116
119
  export const cli = (command: string) => getLogger().cli(command);
117
120
 
121
+ // CLI Primitives (v5.0)
122
+ export const step = (current: number, total: number, message: string) => getLogger().step(current, total, message);
123
+ export const spinner = (message: string) => getLogger().spinner(message);
124
+ export const box = (content: string, options?: IBoxOptions) => getLogger().box(content, options);
125
+ export const cliTable = (rows: Record<string, unknown>[], options?: ITableOptions) => getLogger().cliTable(rows, options);
126
+ export const header = (title: string, subtitle?: string) => getLogger().header(title, subtitle);
127
+ export const divider = () => getLogger().divider();
128
+ export const blank = () => getLogger().blank();
129
+ export const setCLILevel = (level: CLILogLevel) => getLogger().setCLILevel(level);
130
+
118
131
  // Type exports
119
132
  export type {
120
133
  LogLevel,
@@ -152,6 +165,10 @@ export type {
152
165
  ColumnAlign,
153
166
  ColumnConfig,
154
167
  LogOptions,
168
+ CLILogLevel,
169
+ ISpinnerHandle,
170
+ IBoxOptions,
171
+ ITableOptions,
155
172
  } from './types/index.js';
156
173
 
157
174
  // Styling utilities
@@ -371,4 +388,8 @@ export {
371
388
  getEnvironmentInfo,
372
389
  } from './utils/environment-detector.js';
373
390
 
374
- export type { Environment } from './utils/environment-detector.js';
391
+ export type { Environment } from './utils/environment-detector.js';
392
+
393
+ // Output writers for custom log destinations
394
+ export { BufferWriter, type BufferEntry } from './writers/index.js';
395
+ export type { OutputWriter, OutputMode } from './types/core.js';
package/src/types/core.ts CHANGED
@@ -100,6 +100,48 @@ export type ExportFormat = 'json' | 'csv' | 'markdown' | 'plain' | 'html';
100
100
  */
101
101
  export type OutputFormat = 'auto' | 'plain' | 'ansi' | 'build' | 'ci';
102
102
 
103
+ /**
104
+ * Output modes for controlling where logs are written
105
+ * @typedef {'console' | 'silent' | 'custom'} OutputMode
106
+ *
107
+ * @description
108
+ * - console: Standard console.log output (default)
109
+ * - silent: No output at all
110
+ * - custom: Use custom OutputWriter for advanced scenarios
111
+ */
112
+ export type OutputMode = 'console' | 'silent' | 'custom';
113
+
114
+ /**
115
+ * Custom output writer interface for redirecting log output
116
+ *
117
+ * @interface OutputWriter
118
+ * @since 4.0.0
119
+ *
120
+ * @description
121
+ * Allows redirecting log output to custom destinations like:
122
+ * - DraftLog for CLI spinners with concurrent logging
123
+ * - Buffers for collecting logs during operations
124
+ * - Custom streams or transports
125
+ *
126
+ * @example
127
+ * class BufferWriter implements OutputWriter {
128
+ * private buffer: string[] = [];
129
+ *
130
+ * write(message: string, level: LogLevel, styles: string[]): void {
131
+ * this.buffer.push(message);
132
+ * }
133
+ *
134
+ * flush(): void {
135
+ * this.buffer.forEach(msg => console.log(msg));
136
+ * this.buffer = [];
137
+ * }
138
+ * }
139
+ */
140
+ export interface OutputWriter {
141
+ write(message: string, level: LogLevel, styles: string[]): void;
142
+ flush?(): void;
143
+ }
144
+
103
145
  /**
104
146
  * Interfaz de configuración para instancias del logger
105
147
  *
@@ -130,6 +172,12 @@ export interface LoggerConfig {
130
172
  bufferSize?: number;
131
173
  autoDetectTheme?: boolean;
132
174
  outputFormat?: OutputFormat;
175
+ /** Output mode: 'console' (default), 'silent', or 'custom' @since 4.0.0 */
176
+ outputMode?: OutputMode;
177
+ /** Custom writer when outputMode is 'custom' @since 4.0.0 */
178
+ outputWriter?: OutputWriter;
179
+ /** CLI verbosity level for controlling primitive output @since 5.0.0 */
180
+ cliLevel?: CLILogLevel;
133
181
  }
134
182
 
135
183
  /**
@@ -315,4 +363,55 @@ export interface LogOptions {
315
363
  keyValue?: boolean;
316
364
  badgeStyle?: BadgeStyle;
317
365
  timestampFormat?: TimestampFormat;
366
+ }
367
+
368
+ // ===== CLI PRIMITIVES (v5.0) =====
369
+
370
+ /**
371
+ * CLI verbosity levels for controlling primitive output
372
+ * @since 5.0.0
373
+ */
374
+ export type CLILogLevel = 'silent' | 'quiet' | 'normal' | 'verbose' | 'debug';
375
+
376
+ /**
377
+ * Handle returned by logger.spinner() for controlling spinner lifecycle
378
+ * @since 5.0.0
379
+ */
380
+ export interface ISpinnerHandle {
381
+ /** Start the spinner animation */
382
+ start(): void;
383
+ /** Stop the spinner without a status message */
384
+ stop(): void;
385
+ /** Stop the spinner with a success message */
386
+ succeed(msg?: string): void;
387
+ /** Stop the spinner with a failure message */
388
+ fail(msg?: string): void;
389
+ /** Update the spinner text while running */
390
+ text(msg: string): void;
391
+ }
392
+
393
+ /**
394
+ * Options for logger.box() output
395
+ * @since 5.0.0
396
+ */
397
+ export interface IBoxOptions {
398
+ /** Title displayed in the top border */
399
+ title?: string;
400
+ /** Color of the border (hex, CSS name, or ANSI name) */
401
+ borderColor?: string;
402
+ /** Border character style */
403
+ borderStyle?: 'single' | 'double' | 'rounded' | 'bold';
404
+ /** Inner padding lines (default: 0) */
405
+ padding?: number;
406
+ }
407
+
408
+ /**
409
+ * Options for logger.cliTable() output
410
+ * @since 5.0.0
411
+ */
412
+ export interface ITableOptions {
413
+ /** Column names to display (overrides auto-detection) */
414
+ columns?: string[];
415
+ /** Header labels (defaults to column names) */
416
+ head?: string[];
318
417
  }
@@ -30,6 +30,10 @@ export type {
30
30
  ColumnAlign,
31
31
  ColumnConfig,
32
32
  LogOptions,
33
+ CLILogLevel,
34
+ ISpinnerHandle,
35
+ IBoxOptions,
36
+ ITableOptions,
33
37
  } from './core.js';
34
38
 
35
39
  export { LOG_LEVELS } from './core.js';
@@ -0,0 +1,157 @@
1
+ /**
2
+ * @fileoverview BufferWriter - Collects log output in memory for later use
3
+ * @version 4.0.0
4
+ */
5
+
6
+ import type { LogLevel, OutputWriter } from '../types/core.js';
7
+
8
+ /**
9
+ * Entry in the log buffer
10
+ */
11
+ export interface BufferEntry {
12
+ message: string;
13
+ level: LogLevel;
14
+ styles: string[];
15
+ timestamp: number;
16
+ }
17
+
18
+ /**
19
+ * BufferWriter collects log messages in memory instead of outputting to console.
20
+ * Useful for:
21
+ * - CLI operations with spinners (buffer logs during spinner, show after)
22
+ * - Testing (capture logs for assertions)
23
+ * - Batch processing (collect logs, process together)
24
+ *
25
+ * @implements {OutputWriter}
26
+ * @since 4.0.0
27
+ *
28
+ * @example
29
+ * import logger, { BufferWriter } from '@mks2508/better-logger';
30
+ *
31
+ * const buffer = new BufferWriter();
32
+ * logger.updateConfig({
33
+ * outputMode: 'custom',
34
+ * outputWriter: buffer
35
+ * });
36
+ *
37
+ * // Logs go to buffer, not console
38
+ * spinner.start('Loading...');
39
+ * logger.info('Connecting...');
40
+ * logger.info('Processing...');
41
+ * spinner.stop();
42
+ *
43
+ * // Show buffered logs
44
+ * logger.updateConfig({ outputMode: 'console' });
45
+ * buffer.flush(); // Outputs all buffered logs to console
46
+ */
47
+ export class BufferWriter implements OutputWriter {
48
+ private buffer: BufferEntry[] = [];
49
+ private maxSize: number;
50
+
51
+ /**
52
+ * Creates a new BufferWriter
53
+ * @param maxSize - Maximum number of entries to buffer (default: 1000)
54
+ */
55
+ constructor(maxSize: number = 1000) {
56
+ this.maxSize = maxSize;
57
+ }
58
+
59
+ /**
60
+ * Writes a log entry to the buffer
61
+ * @param message - Formatted log message
62
+ * @param level - Log level
63
+ * @param styles - CSS styles (for browser console)
64
+ */
65
+ write(message: string, level: LogLevel, styles: string[]): void {
66
+ if (this.buffer.length >= this.maxSize) {
67
+ this.buffer.shift(); // Remove oldest entry
68
+ }
69
+
70
+ this.buffer.push({
71
+ message,
72
+ level,
73
+ styles,
74
+ timestamp: Date.now()
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Returns all buffered entries
80
+ * @returns Copy of the buffer array
81
+ */
82
+ getBuffer(): BufferEntry[] {
83
+ return [...this.buffer];
84
+ }
85
+
86
+ /**
87
+ * Returns buffered entries filtered by log level
88
+ * @param levels - Log levels to include
89
+ * @returns Filtered buffer entries
90
+ */
91
+ getByLevel(...levels: LogLevel[]): BufferEntry[] {
92
+ return this.buffer.filter(entry => levels.includes(entry.level));
93
+ }
94
+
95
+ /**
96
+ * Returns the number of buffered entries
97
+ */
98
+ get size(): number {
99
+ return this.buffer.length;
100
+ }
101
+
102
+ /**
103
+ * Checks if buffer is empty
104
+ */
105
+ get isEmpty(): boolean {
106
+ return this.buffer.length === 0;
107
+ }
108
+
109
+ /**
110
+ * Clears all buffered entries
111
+ */
112
+ clear(): void {
113
+ this.buffer = [];
114
+ }
115
+
116
+ /**
117
+ * Outputs all buffered entries to console and clears the buffer
118
+ */
119
+ flush(): void {
120
+ this.buffer.forEach(entry => {
121
+ if (entry.styles.length > 0) {
122
+ console.log(entry.message, ...entry.styles);
123
+ } else {
124
+ console.log(entry.message);
125
+ }
126
+ });
127
+ this.clear();
128
+ }
129
+
130
+ /**
131
+ * Outputs buffered entries to console without clearing
132
+ */
133
+ replay(): void {
134
+ this.buffer.forEach(entry => {
135
+ if (entry.styles.length > 0) {
136
+ console.log(entry.message, ...entry.styles);
137
+ } else {
138
+ console.log(entry.message);
139
+ }
140
+ });
141
+ }
142
+
143
+ /**
144
+ * Returns all messages as an array of strings
145
+ */
146
+ toArray(): string[] {
147
+ return this.buffer.map(entry => entry.message);
148
+ }
149
+
150
+ /**
151
+ * Returns all messages joined as a single string
152
+ * @param separator - String to join messages with (default: newline)
153
+ */
154
+ toString(separator: string = '\n'): string {
155
+ return this.toArray().join(separator);
156
+ }
157
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Output writers for better-logger
3
+ * @version 4.0.0
4
+ */
5
+
6
+ export { BufferWriter, type BufferEntry } from './BufferWriter.js';
package/vite.config.ts CHANGED
@@ -57,6 +57,7 @@ const buildConfigs = {
57
57
  entry: {
58
58
  index: resolve(__dirname, 'src/index.ts'),
59
59
  core: resolve(__dirname, 'src/core.ts'),
60
+ cli: resolve(__dirname, 'src/cli-module.ts'),
60
61
  styling: resolve(__dirname, 'src/styling-module.ts'),
61
62
  exports: resolve(__dirname, 'src/exports-module.ts')
62
63
  },
@@ -210,6 +211,38 @@ const buildConfigs = {
210
211
  }
211
212
  }
212
213
  }
214
+ },
215
+
216
+ // Build modular - Solo CLI primitives (spinners, boxes, tables, steps)
217
+ cli: {
218
+ ...baseConfig,
219
+ plugins: [
220
+ dts({
221
+ ...baseConfig.plugins[0].options,
222
+ outDir: 'packages/cli/dist/types',
223
+ include: ['src/cli-module.ts', 'src/cli-primitives/**/*', 'src/types/**/*', 'src/terminal/**/*', 'src/utils/environment-detector.ts'],
224
+ })
225
+ ],
226
+ build: {
227
+ ...baseConfig.build,
228
+ outDir: 'packages/cli/dist',
229
+ lib: {
230
+ entry: resolve(__dirname, 'src/cli-module.ts'),
231
+ name: 'BetterLoggerCLI',
232
+ formats: ['es', 'cjs'],
233
+ fileName: (format) => {
234
+ const ext = format === 'cjs' ? 'cjs' : 'js';
235
+ return `index.${ext}`;
236
+ }
237
+ },
238
+ rollupOptions: {
239
+ external: [],
240
+ output: {
241
+ globals: {},
242
+ exports: 'named'
243
+ }
244
+ }
245
+ }
213
246
  }
214
247
  };
215
248