@mks2508/better-logger 4.0.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.
- package/CHANGELOG.json +23 -1
- package/dist/Logger.d.ts +117 -4
- package/dist/Logger.d.ts.map +1 -1
- package/dist/ScopedLogger.d.ts +17 -0
- package/dist/ScopedLogger.d.ts.map +1 -1
- package/dist/chunks/{Logger-D-gmmgR2.js → Logger-BZ7B7OXE.js} +228 -175
- package/dist/chunks/Logger-BZ7B7OXE.js.map +1 -0
- package/dist/chunks/Logger-Cbi1f10o.js +2 -0
- package/dist/chunks/Logger-Cbi1f10o.js.map +1 -0
- package/dist/chunks/cli-module-CadqgZ1Z.js +2 -0
- package/dist/chunks/cli-module-CadqgZ1Z.js.map +1 -0
- package/dist/chunks/cli-module-ClIJmaT8.js +383 -0
- package/dist/chunks/cli-module-ClIJmaT8.js.map +1 -0
- package/dist/chunks/color-converter-CCSQRztd.js +2 -0
- package/dist/chunks/color-converter-CCSQRztd.js.map +1 -0
- package/dist/chunks/color-converter-_Xdmsy7E.js +462 -0
- package/dist/chunks/color-converter-_Xdmsy7E.js.map +1 -0
- package/dist/chunks/{environment-COWvu6Wz.js → environment-C1xxvc8l.js} +26 -476
- package/dist/chunks/environment-C1xxvc8l.js.map +1 -0
- package/dist/chunks/environment-Cprkw3g9.js +4 -0
- package/dist/chunks/environment-Cprkw3g9.js.map +1 -0
- package/dist/chunks/{formatting-CYjT9yhO.js → formatting-DMJxYq9o.js} +18 -18
- package/dist/chunks/{formatting-CYjT9yhO.js.map → formatting-DMJxYq9o.js.map} +1 -1
- package/dist/chunks/{formatting-Cg5YhB9Y.js → formatting-DpKxCsXq.js} +2 -2
- package/dist/chunks/{formatting-Cg5YhB9Y.js.map → formatting-DpKxCsXq.js.map} +1 -1
- package/dist/cli-module.d.ts +15 -0
- package/dist/cli-module.d.ts.map +1 -0
- package/dist/cli-primitives/box.d.ts +11 -0
- package/dist/cli-primitives/box.d.ts.map +1 -0
- package/dist/cli-primitives/cli-table.d.ts +11 -0
- package/dist/cli-primitives/cli-table.d.ts.map +1 -0
- package/dist/cli-primitives/divider.d.ts +11 -0
- package/dist/cli-primitives/divider.d.ts.map +1 -0
- package/dist/cli-primitives/header.d.ts +12 -0
- package/dist/cli-primitives/header.d.ts.map +1 -0
- package/dist/cli-primitives/index.d.ts +13 -0
- package/dist/cli-primitives/index.d.ts.map +1 -0
- package/dist/cli-primitives/server-fallback.d.ts +25 -0
- package/dist/cli-primitives/server-fallback.d.ts.map +1 -0
- package/dist/cli-primitives/spinner.d.ts +47 -0
- package/dist/cli-primitives/spinner.d.ts.map +1 -0
- package/dist/cli-primitives/step.d.ts +11 -0
- package/dist/cli-primitives/step.d.ts.map +1 -0
- package/dist/cli.cjs +2 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.js +12 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants.d.ts +9 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.js +2 -2
- package/dist/exports-module.d.ts +1 -1
- package/dist/exports-module.d.ts.map +1 -1
- package/dist/exports.cjs +1 -1
- package/dist/exports.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +71 -53
- package/dist/index.js.map +1 -1
- package/dist/styling-module.d.ts +1 -1
- package/dist/styling-module.d.ts.map +1 -1
- package/dist/styling.cjs +1 -1
- package/dist/styling.js +3 -3
- package/dist/types/core.d.ts +47 -0
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +28 -3
- package/packages/core/package.json +1 -1
- package/playground/demo-all.ts +95 -0
- package/playground/demo-box.ts +85 -0
- package/playground/demo-levels.ts +56 -0
- package/playground/demo-real-world.ts +98 -0
- package/playground/demo-spinner.ts +77 -0
- package/playground/demo-steps.ts +72 -0
- package/playground/demo-table.ts +83 -0
- package/src/Logger.ts +213 -8
- package/src/ScopedLogger.ts +43 -1
- package/src/cli-module.ts +21 -0
- package/src/cli-primitives/box.ts +86 -0
- package/src/cli-primitives/cli-table.ts +62 -0
- package/src/cli-primitives/divider.ts +17 -0
- package/src/cli-primitives/header.ts +18 -0
- package/src/cli-primitives/index.ts +13 -0
- package/src/cli-primitives/server-fallback.ts +54 -0
- package/src/cli-primitives/spinner.ts +133 -0
- package/src/cli-primitives/step.ts +22 -0
- package/src/constants.ts +14 -2
- package/src/index.ts +18 -1
- package/src/types/core.ts +53 -0
- package/src/types/index.ts +4 -0
- package/vite.config.ts +33 -0
- package/dist/chunks/Logger-D-gmmgR2.js.map +0 -1
- package/dist/chunks/Logger-D7cfaz15.js +0 -2
- package/dist/chunks/Logger-D7cfaz15.js.map +0 -1
- package/dist/chunks/environment-COWvu6Wz.js.map +0 -1
- package/dist/chunks/environment-C_8J-zQ_.js +0 -4
- package/dist/chunks/environment-C_8J-zQ_.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* setCLILevel() toggling: silent → quiet → normal → verbose.
|
|
3
|
+
* Run: bun playground/demo-levels.ts
|
|
4
|
+
*/
|
|
5
|
+
import { Logger } from '../src/Logger.js';
|
|
6
|
+
import type { CLILogLevel } from '../src/types/index.js';
|
|
7
|
+
|
|
8
|
+
const logger = new Logger();
|
|
9
|
+
|
|
10
|
+
function demonstrateLevel(level: CLILogLevel) {
|
|
11
|
+
logger.setCLILevel(level);
|
|
12
|
+
process.stderr.write(`\n── setCLILevel('${level}') ──\n`);
|
|
13
|
+
|
|
14
|
+
// Try each primitive
|
|
15
|
+
logger.header('Header', 'subtitle');
|
|
16
|
+
logger.divider();
|
|
17
|
+
logger.step(1, 3, 'Step message');
|
|
18
|
+
logger.box('Box content', { title: 'Box', borderStyle: 'rounded' });
|
|
19
|
+
logger.cliTable([{ key: 'value', status: 'ok' }]);
|
|
20
|
+
logger.blank();
|
|
21
|
+
|
|
22
|
+
// Also test regular log methods
|
|
23
|
+
logger.info('info message');
|
|
24
|
+
logger.warn('warn message');
|
|
25
|
+
logger.error('error message');
|
|
26
|
+
|
|
27
|
+
process.stderr.write(`── end '${level}' ──\n`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function main() {
|
|
31
|
+
// Start with a visible header
|
|
32
|
+
logger.setCLILevel('normal');
|
|
33
|
+
logger.header('CLI Level Demos');
|
|
34
|
+
logger.divider();
|
|
35
|
+
|
|
36
|
+
logger.info('Each level sets verbosity + primitive visibility:');
|
|
37
|
+
logger.info(' silent → no output at all');
|
|
38
|
+
logger.info(' quiet → errors only, primitives hidden');
|
|
39
|
+
logger.info(' normal → info+, primitives visible');
|
|
40
|
+
logger.info(' verbose → debug+, primitives visible');
|
|
41
|
+
logger.blank();
|
|
42
|
+
|
|
43
|
+
// Demonstrate each level
|
|
44
|
+
const levels: CLILogLevel[] = ['silent', 'quiet', 'normal', 'verbose'];
|
|
45
|
+
for (const level of levels) {
|
|
46
|
+
demonstrateLevel(level);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Restore to normal
|
|
50
|
+
logger.setCLILevel('normal');
|
|
51
|
+
logger.blank();
|
|
52
|
+
logger.divider();
|
|
53
|
+
logger.info('Level demos complete. Restored to "normal".');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Real-world simulation: a commit-wizard-like CLI workflow.
|
|
3
|
+
* Run: bun playground/demo-real-world.ts
|
|
4
|
+
*/
|
|
5
|
+
import { Logger } from '../src/Logger.js';
|
|
6
|
+
|
|
7
|
+
const logger = new Logger();
|
|
8
|
+
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
// ── Startup ───────────────────────────────────────
|
|
12
|
+
logger.header('Commit Wizard', 'v2.0.0');
|
|
13
|
+
logger.divider();
|
|
14
|
+
logger.blank();
|
|
15
|
+
|
|
16
|
+
// ── Step 1: Analyze repository ────────────────────
|
|
17
|
+
logger.step(1, 5, 'Analyzing repository...');
|
|
18
|
+
const s1 = logger.spinner('Loading git diff...');
|
|
19
|
+
s1.start();
|
|
20
|
+
await sleep(1200);
|
|
21
|
+
s1.succeed('3 files changed, 47 insertions, 12 deletions');
|
|
22
|
+
logger.blank();
|
|
23
|
+
|
|
24
|
+
// ── Step 2: Detect provider ───────────────────────
|
|
25
|
+
logger.step(2, 5, 'Detecting provider...');
|
|
26
|
+
await sleep(300);
|
|
27
|
+
|
|
28
|
+
logger.cliTable([
|
|
29
|
+
{ provider: 'Gemini SDK', key: 'GEMINI_API_KEY', status: 'not set' },
|
|
30
|
+
{ provider: 'Groq', key: 'GROQ_API_KEY', status: 'found ✓' },
|
|
31
|
+
{ provider: 'OpenRouter', key: 'OPENROUTER_API_KEY', status: 'not set' },
|
|
32
|
+
{ provider: 'Gemini CLI', key: 'binary', status: 'not found' },
|
|
33
|
+
]);
|
|
34
|
+
logger.blank();
|
|
35
|
+
logger.info(' Using provider: Groq (llama-3.3-70b-versatile)');
|
|
36
|
+
logger.blank();
|
|
37
|
+
|
|
38
|
+
// ── Step 3: Generate commit ───────────────────────
|
|
39
|
+
logger.step(3, 5, 'Generating commit message...');
|
|
40
|
+
const s3 = logger.spinner('AI thinking...');
|
|
41
|
+
s3.start();
|
|
42
|
+
await sleep(800);
|
|
43
|
+
s3.text('Analyzing diff patterns...');
|
|
44
|
+
await sleep(600);
|
|
45
|
+
s3.text('Composing message...');
|
|
46
|
+
await sleep(600);
|
|
47
|
+
s3.succeed('Commit message generated');
|
|
48
|
+
logger.blank();
|
|
49
|
+
|
|
50
|
+
logger.box(
|
|
51
|
+
[
|
|
52
|
+
'feat(providers): add multi-provider AI support',
|
|
53
|
+
'',
|
|
54
|
+
'Implement Gemini SDK, Groq, and OpenRouter providers',
|
|
55
|
+
'with automatic detection based on available API keys.',
|
|
56
|
+
'',
|
|
57
|
+
'<technical>',
|
|
58
|
+
'- Added GeminiSdkProvider, GroqProvider, OpenRouterProvider classes',
|
|
59
|
+
'- Factory function with priority-based auto-detection',
|
|
60
|
+
'- Shared IAIProvider interface for all implementations',
|
|
61
|
+
'</technical>',
|
|
62
|
+
'',
|
|
63
|
+
'<changelog>',
|
|
64
|
+
'## Feature 🚀',
|
|
65
|
+
'Multi-provider AI support with automatic fallback',
|
|
66
|
+
'</changelog>',
|
|
67
|
+
].join('\n'),
|
|
68
|
+
{ title: 'Commit #1', borderStyle: 'rounded', borderColor: '#ff6b6b' },
|
|
69
|
+
);
|
|
70
|
+
logger.blank();
|
|
71
|
+
|
|
72
|
+
// ── Step 4: Apply commit ──────────────────────────
|
|
73
|
+
logger.step(4, 5, 'Applying commit...');
|
|
74
|
+
const s4 = logger.spinner('Running git commit...');
|
|
75
|
+
s4.start();
|
|
76
|
+
await sleep(800);
|
|
77
|
+
s4.succeed('Commit applied: abc1234');
|
|
78
|
+
logger.blank();
|
|
79
|
+
|
|
80
|
+
// ── Step 5: Done ──────────────────────────────────
|
|
81
|
+
logger.step(5, 5, 'Done');
|
|
82
|
+
logger.blank();
|
|
83
|
+
|
|
84
|
+
logger.box(
|
|
85
|
+
[
|
|
86
|
+
'1 commit applied successfully',
|
|
87
|
+
'',
|
|
88
|
+
'Provider: Groq',
|
|
89
|
+
'Model: llama-3.3-70b-versatile',
|
|
90
|
+
'Time: 2.4s',
|
|
91
|
+
].join('\n'),
|
|
92
|
+
{ title: 'Summary', borderStyle: 'rounded', borderColor: '#00ff00' },
|
|
93
|
+
);
|
|
94
|
+
logger.blank();
|
|
95
|
+
logger.divider();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spinner lifecycle: start, text update, succeed/fail.
|
|
3
|
+
* Run: bun playground/demo-spinner.ts
|
|
4
|
+
*/
|
|
5
|
+
import { Logger } from '../src/Logger.js';
|
|
6
|
+
|
|
7
|
+
const logger = new Logger();
|
|
8
|
+
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
logger.header('Spinner Demos');
|
|
12
|
+
logger.divider();
|
|
13
|
+
logger.blank();
|
|
14
|
+
|
|
15
|
+
// ── Basic spinner → succeed ───────────────────────
|
|
16
|
+
logger.info('1. Basic spinner with succeed');
|
|
17
|
+
const s1 = logger.spinner('Installing dependencies...');
|
|
18
|
+
s1.start();
|
|
19
|
+
await sleep(1500);
|
|
20
|
+
s1.succeed('Dependencies installed');
|
|
21
|
+
logger.blank();
|
|
22
|
+
|
|
23
|
+
// ── Spinner with text() update ────────────────────
|
|
24
|
+
logger.info('2. Spinner with text update');
|
|
25
|
+
const s2 = logger.spinner('Downloading package 1/3...');
|
|
26
|
+
s2.start();
|
|
27
|
+
await sleep(800);
|
|
28
|
+
s2.text('Downloading package 2/3...');
|
|
29
|
+
await sleep(800);
|
|
30
|
+
s2.text('Downloading package 3/3...');
|
|
31
|
+
await sleep(800);
|
|
32
|
+
s2.succeed('All packages downloaded');
|
|
33
|
+
logger.blank();
|
|
34
|
+
|
|
35
|
+
// ── Spinner → fail ────────────────────────────────
|
|
36
|
+
logger.info('3. Spinner with fail');
|
|
37
|
+
const s3 = logger.spinner('Connecting to database...');
|
|
38
|
+
s3.start();
|
|
39
|
+
await sleep(1200);
|
|
40
|
+
s3.fail('Connection refused on port 5432');
|
|
41
|
+
logger.blank();
|
|
42
|
+
|
|
43
|
+
// ── Multiple sequential spinners ──────────────────
|
|
44
|
+
logger.info('4. Sequential spinners');
|
|
45
|
+
const tasks = [
|
|
46
|
+
'Compiling TypeScript...',
|
|
47
|
+
'Running linter...',
|
|
48
|
+
'Building bundles...',
|
|
49
|
+
'Generating types...',
|
|
50
|
+
];
|
|
51
|
+
for (const task of tasks) {
|
|
52
|
+
const s = logger.spinner(task);
|
|
53
|
+
s.start();
|
|
54
|
+
await sleep(700);
|
|
55
|
+
s.succeed();
|
|
56
|
+
}
|
|
57
|
+
logger.blank();
|
|
58
|
+
|
|
59
|
+
// ── Spinner concurrent with logger.info ───────────
|
|
60
|
+
logger.info('5. Spinner with interleaved log messages');
|
|
61
|
+
const s5 = logger.spinner('Processing files...');
|
|
62
|
+
s5.start();
|
|
63
|
+
await sleep(400);
|
|
64
|
+
logger.info(' Found 42 files');
|
|
65
|
+
await sleep(400);
|
|
66
|
+
logger.info(' Processed batch 1');
|
|
67
|
+
await sleep(400);
|
|
68
|
+
logger.info(' Processed batch 2');
|
|
69
|
+
await sleep(400);
|
|
70
|
+
s5.succeed('All files processed');
|
|
71
|
+
logger.blank();
|
|
72
|
+
|
|
73
|
+
logger.divider();
|
|
74
|
+
logger.info('Spinner demos complete.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step progress walkthrough with simulated work delays.
|
|
3
|
+
* Run: bun playground/demo-steps.ts
|
|
4
|
+
*/
|
|
5
|
+
import { Logger } from '../src/Logger.js';
|
|
6
|
+
|
|
7
|
+
const logger = new Logger();
|
|
8
|
+
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
|
|
9
|
+
|
|
10
|
+
async function main() {
|
|
11
|
+
logger.header('Step Progress Demos');
|
|
12
|
+
logger.divider();
|
|
13
|
+
logger.blank();
|
|
14
|
+
|
|
15
|
+
// ── Basic step sequence ───────────────────────────
|
|
16
|
+
logger.info('1. Basic step sequence');
|
|
17
|
+
logger.blank();
|
|
18
|
+
|
|
19
|
+
const steps = [
|
|
20
|
+
'Reading configuration...',
|
|
21
|
+
'Validating schema...',
|
|
22
|
+
'Compiling sources...',
|
|
23
|
+
'Running tests...',
|
|
24
|
+
'Generating output...',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < steps.length; i++) {
|
|
28
|
+
logger.step(i + 1, steps.length, steps[i]);
|
|
29
|
+
await sleep(300);
|
|
30
|
+
}
|
|
31
|
+
logger.blank();
|
|
32
|
+
|
|
33
|
+
// ── Steps combined with spinners ──────────────────
|
|
34
|
+
logger.info('2. Steps with spinners');
|
|
35
|
+
logger.blank();
|
|
36
|
+
|
|
37
|
+
logger.step(1, 3, 'Fetching remote data');
|
|
38
|
+
const s1 = logger.spinner('Downloading manifest...');
|
|
39
|
+
s1.start();
|
|
40
|
+
await sleep(1000);
|
|
41
|
+
s1.succeed('Manifest downloaded (2.3 KB)');
|
|
42
|
+
|
|
43
|
+
logger.step(2, 3, 'Processing data');
|
|
44
|
+
const s2 = logger.spinner('Parsing JSON...');
|
|
45
|
+
s2.start();
|
|
46
|
+
await sleep(600);
|
|
47
|
+
s2.text('Validating entries...');
|
|
48
|
+
await sleep(600);
|
|
49
|
+
s2.succeed('42 entries validated');
|
|
50
|
+
|
|
51
|
+
logger.step(3, 3, 'Writing output');
|
|
52
|
+
const s3 = logger.spinner('Generating report...');
|
|
53
|
+
s3.start();
|
|
54
|
+
await sleep(800);
|
|
55
|
+
s3.succeed('Report saved to ./output/report.json');
|
|
56
|
+
logger.blank();
|
|
57
|
+
|
|
58
|
+
// ── Many steps ────────────────────────────────────
|
|
59
|
+
logger.info('3. Long step sequence (10 steps)');
|
|
60
|
+
logger.blank();
|
|
61
|
+
|
|
62
|
+
for (let i = 1; i <= 10; i++) {
|
|
63
|
+
logger.step(i, 10, `Migration step ${i}`);
|
|
64
|
+
await sleep(150);
|
|
65
|
+
}
|
|
66
|
+
logger.blank();
|
|
67
|
+
|
|
68
|
+
logger.divider();
|
|
69
|
+
logger.info('Step demos complete.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI table — various column counts, auto-width, explicit columns.
|
|
3
|
+
* Run: bun playground/demo-table.ts
|
|
4
|
+
*/
|
|
5
|
+
import { Logger } from '../src/Logger.js';
|
|
6
|
+
|
|
7
|
+
const logger = new Logger();
|
|
8
|
+
|
|
9
|
+
function main() {
|
|
10
|
+
logger.header('Table Demos');
|
|
11
|
+
logger.divider();
|
|
12
|
+
logger.blank();
|
|
13
|
+
|
|
14
|
+
// ── Auto-detect columns from data ─────────────────
|
|
15
|
+
logger.info('1. Auto-detected columns');
|
|
16
|
+
logger.blank();
|
|
17
|
+
|
|
18
|
+
logger.cliTable([
|
|
19
|
+
{ name: 'Gemini SDK', version: '1.0.0', status: 'active' },
|
|
20
|
+
{ name: 'Groq SDK', version: '0.8.2', status: 'active' },
|
|
21
|
+
{ name: 'OpenRouter', version: '2.1.0', status: 'fallback' },
|
|
22
|
+
]);
|
|
23
|
+
logger.blank();
|
|
24
|
+
|
|
25
|
+
// ── Explicit columns via options ──────────────────
|
|
26
|
+
logger.info('2. Explicit columns (subset)');
|
|
27
|
+
logger.blank();
|
|
28
|
+
|
|
29
|
+
logger.cliTable(
|
|
30
|
+
[
|
|
31
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com', role: 'admin' },
|
|
32
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com', role: 'user' },
|
|
33
|
+
{ id: 3, name: 'Charlie', email: 'charlie@example.com', role: 'user' },
|
|
34
|
+
],
|
|
35
|
+
{ columns: ['name', 'role'] },
|
|
36
|
+
);
|
|
37
|
+
logger.blank();
|
|
38
|
+
|
|
39
|
+
// ── Various value lengths ─────────────────────────
|
|
40
|
+
logger.info('3. Mixed value lengths');
|
|
41
|
+
logger.blank();
|
|
42
|
+
|
|
43
|
+
logger.cliTable([
|
|
44
|
+
{ key: 'a', value: 'short' },
|
|
45
|
+
{ key: 'longer-key-name', value: 'This is a much longer value to test column sizing' },
|
|
46
|
+
{ key: 'b', value: '42' },
|
|
47
|
+
]);
|
|
48
|
+
logger.blank();
|
|
49
|
+
|
|
50
|
+
// ── Numeric and boolean values ────────────────────
|
|
51
|
+
logger.info('4. Numeric and boolean values');
|
|
52
|
+
logger.blank();
|
|
53
|
+
|
|
54
|
+
logger.cliTable([
|
|
55
|
+
{ metric: 'Requests/sec', value: 12500, healthy: true },
|
|
56
|
+
{ metric: 'Avg latency', value: 23.4, healthy: true },
|
|
57
|
+
{ metric: 'Error rate', value: 0.02, healthy: true },
|
|
58
|
+
{ metric: 'Memory (MB)', value: 512, healthy: false },
|
|
59
|
+
]);
|
|
60
|
+
logger.blank();
|
|
61
|
+
|
|
62
|
+
// ── Many columns ──────────────────────────────────
|
|
63
|
+
logger.info('5. Many columns');
|
|
64
|
+
logger.blank();
|
|
65
|
+
|
|
66
|
+
logger.cliTable([
|
|
67
|
+
{ col1: 'A', col2: 'B', col3: 'C', col4: 'D', col5: 'E', col6: 'F' },
|
|
68
|
+
{ col1: '1', col2: '2', col3: '3', col4: '4', col5: '5', col6: '6' },
|
|
69
|
+
]);
|
|
70
|
+
logger.blank();
|
|
71
|
+
|
|
72
|
+
// ── Single row ────────────────────────────────────
|
|
73
|
+
logger.info('6. Single row');
|
|
74
|
+
logger.blank();
|
|
75
|
+
|
|
76
|
+
logger.cliTable([{ provider: 'Gemini SDK', model: 'gemini-2.5-flash', latency: '120ms' }]);
|
|
77
|
+
logger.blank();
|
|
78
|
+
|
|
79
|
+
logger.divider();
|
|
80
|
+
logger.info('Table demos complete.');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
main();
|
package/src/Logger.ts
CHANGED
|
@@ -36,7 +36,7 @@ import { TransportManager } from './transports/index.js';
|
|
|
36
36
|
import { parseStackTrace } from './utils/stackTrace.js';
|
|
37
37
|
import { formatTimestamp } from './utils/timestamps.js';
|
|
38
38
|
import { createStyledOutput, setupThemeChangeListener } from './utils/output.js';
|
|
39
|
-
import { getEnvironment, getColorCapability } from './utils/environment-detector.js';
|
|
39
|
+
import { getEnvironment, getColorCapability, isRunningInTerminal } from './utils/environment-detector.js';
|
|
40
40
|
import { formatBadge } from './terminal/formatter.js';
|
|
41
41
|
|
|
42
42
|
// Styling imports
|
|
@@ -62,7 +62,17 @@ import { ExportLogHandler } from './handlers/index.js';
|
|
|
62
62
|
import { createDefaultCLI, type CommandProcessor } from './cli/index.js';
|
|
63
63
|
|
|
64
64
|
// Constants
|
|
65
|
-
import { DEFAULT_CONFIG } from './constants.js';
|
|
65
|
+
import { DEFAULT_CONFIG, CLI_LEVEL_MAP } from './constants.js';
|
|
66
|
+
|
|
67
|
+
// CLI Primitives
|
|
68
|
+
import type { CLILogLevel, ISpinnerHandle, IBoxOptions, ITableOptions } from './types/index.js';
|
|
69
|
+
import { renderStep } from './cli-primitives/step.js';
|
|
70
|
+
import { renderHeader } from './cli-primitives/header.js';
|
|
71
|
+
import { renderDivider } from './cli-primitives/divider.js';
|
|
72
|
+
import { renderBox } from './cli-primitives/box.js';
|
|
73
|
+
import { renderTable } from './cli-primitives/cli-table.js';
|
|
74
|
+
import { SpinnerManager, NoopSpinner } from './cli-primitives/spinner.js';
|
|
75
|
+
import { ServerFallback } from './cli-primitives/server-fallback.js';
|
|
66
76
|
|
|
67
77
|
/**
|
|
68
78
|
* Estilos del tema activo actual
|
|
@@ -116,6 +126,11 @@ export class Logger {
|
|
|
116
126
|
private hookManager: HookManager;
|
|
117
127
|
private transportManager?: TransportManager;
|
|
118
128
|
|
|
129
|
+
/** Whether CLI primitives (step, box, header, etc.) should be shown @since 5.0.0 */
|
|
130
|
+
private _showPrimitives = true;
|
|
131
|
+
/** Server-mode fallback for non-TTY environments @since 5.0.0 */
|
|
132
|
+
private _serverFallback?: ServerFallback;
|
|
133
|
+
|
|
119
134
|
/**
|
|
120
135
|
* Crea una nueva instancia del Logger
|
|
121
136
|
*
|
|
@@ -1292,21 +1307,22 @@ export class Logger {
|
|
|
1292
1307
|
|
|
1293
1308
|
/**
|
|
1294
1309
|
* Finaliza un temporizador y muestra el tiempo transcurrido
|
|
1295
|
-
*
|
|
1310
|
+
*
|
|
1296
1311
|
* @param {string} label - Etiqueta del temporizador a finalizar
|
|
1297
|
-
*
|
|
1312
|
+
* @returns {number} Elapsed milliseconds, or -1 if timer not found
|
|
1313
|
+
*
|
|
1298
1314
|
* @example
|
|
1299
1315
|
* logger.time('consulta-db');
|
|
1300
1316
|
* await consultarBaseDatos();
|
|
1301
|
-
* logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
|
|
1302
|
-
*
|
|
1317
|
+
* const elapsed = logger.timeEnd('consulta-db'); // ⏱️ Timer ended: consulta-db - 234.56ms
|
|
1318
|
+
*
|
|
1303
1319
|
* @since 0.3.0
|
|
1304
1320
|
*/
|
|
1305
|
-
timeEnd(label: string):
|
|
1321
|
+
timeEnd(label: string): number {
|
|
1306
1322
|
const timer = this.timers.get(label);
|
|
1307
1323
|
if (!timer) {
|
|
1308
1324
|
this.warn(`Timer '${label}' does not exist`);
|
|
1309
|
-
return;
|
|
1325
|
+
return -1;
|
|
1310
1326
|
}
|
|
1311
1327
|
|
|
1312
1328
|
const elapsed = performance.now() - timer.startTime;
|
|
@@ -1314,6 +1330,8 @@ export class Logger {
|
|
|
1314
1330
|
|
|
1315
1331
|
const timerStyle = StylePresets.success().build();
|
|
1316
1332
|
console.log(`%c⏱️ Timer ended: ${label} - ${elapsed.toFixed(2)}ms`, timerStyle);
|
|
1333
|
+
|
|
1334
|
+
return elapsed;
|
|
1317
1335
|
}
|
|
1318
1336
|
|
|
1319
1337
|
// ===== ADVANCED VISUAL FEATURES =====
|
|
@@ -1462,6 +1480,193 @@ export class Logger {
|
|
|
1462
1480
|
}
|
|
1463
1481
|
}
|
|
1464
1482
|
|
|
1483
|
+
// ===== CLI PRIMITIVES (v5.0) =====
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* Displays a step progress indicator in the terminal
|
|
1487
|
+
*
|
|
1488
|
+
* @param {number} current - Current step number
|
|
1489
|
+
* @param {number} total - Total number of steps
|
|
1490
|
+
* @param {string} message - Step description
|
|
1491
|
+
*
|
|
1492
|
+
* @example
|
|
1493
|
+
* logger.step(1, 5, 'Analyzing repository...');
|
|
1494
|
+
* logger.step(2, 5, 'Generating commit message...');
|
|
1495
|
+
*
|
|
1496
|
+
* @since 5.0.0
|
|
1497
|
+
*/
|
|
1498
|
+
step(current: number, total: number, message: string): void {
|
|
1499
|
+
if (!this._showPrimitives) return;
|
|
1500
|
+
if (!isRunningInTerminal()) {
|
|
1501
|
+
this.getServerFallback().step(current, total, message);
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
const colorCap = getColorCapability();
|
|
1505
|
+
const output = renderStep(current, total, message, colorCap);
|
|
1506
|
+
process.stderr.write(output + '\n');
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
/**
|
|
1510
|
+
* Displays a styled header with optional subtitle
|
|
1511
|
+
*
|
|
1512
|
+
* @param {string} title - Main title text
|
|
1513
|
+
* @param {string} subtitle - Optional subtitle (rendered dimmed)
|
|
1514
|
+
*
|
|
1515
|
+
* @example
|
|
1516
|
+
* logger.header('Commit Wizard', 'v2.0.0');
|
|
1517
|
+
*
|
|
1518
|
+
* @since 5.0.0
|
|
1519
|
+
*/
|
|
1520
|
+
header(title: string, subtitle?: string): void {
|
|
1521
|
+
if (!this._showPrimitives) return;
|
|
1522
|
+
if (!isRunningInTerminal()) {
|
|
1523
|
+
this.getServerFallback().header(title, subtitle);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
const output = renderHeader(title, subtitle);
|
|
1527
|
+
process.stderr.write(output + '\n');
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* Displays a horizontal divider line
|
|
1532
|
+
*
|
|
1533
|
+
* @example
|
|
1534
|
+
* logger.divider();
|
|
1535
|
+
*
|
|
1536
|
+
* @since 5.0.0
|
|
1537
|
+
*/
|
|
1538
|
+
divider(): void {
|
|
1539
|
+
if (!this._showPrimitives) return;
|
|
1540
|
+
if (!isRunningInTerminal()) {
|
|
1541
|
+
this.getServerFallback().divider();
|
|
1542
|
+
return;
|
|
1543
|
+
}
|
|
1544
|
+
const output = renderDivider();
|
|
1545
|
+
process.stderr.write(output + '\n');
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
/**
|
|
1549
|
+
* Outputs a blank line
|
|
1550
|
+
*
|
|
1551
|
+
* @example
|
|
1552
|
+
* logger.blank();
|
|
1553
|
+
*
|
|
1554
|
+
* @since 5.0.0
|
|
1555
|
+
*/
|
|
1556
|
+
blank(): void {
|
|
1557
|
+
if (!this._showPrimitives) return;
|
|
1558
|
+
if (!isRunningInTerminal()) {
|
|
1559
|
+
this.getServerFallback().blank();
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
process.stderr.write('\n');
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/**
|
|
1566
|
+
* Renders content inside a bordered box
|
|
1567
|
+
*
|
|
1568
|
+
* @param {string} content - Content string (may contain newlines)
|
|
1569
|
+
* @param {IBoxOptions} options - Box rendering options
|
|
1570
|
+
*
|
|
1571
|
+
* @example
|
|
1572
|
+
* logger.box('3 commits generated\nProvider: Groq', { title: 'Done', borderColor: '#00ff00' });
|
|
1573
|
+
*
|
|
1574
|
+
* @since 5.0.0
|
|
1575
|
+
*/
|
|
1576
|
+
box(content: string, options?: IBoxOptions): void {
|
|
1577
|
+
if (!this._showPrimitives) return;
|
|
1578
|
+
if (!isRunningInTerminal()) {
|
|
1579
|
+
this.getServerFallback().box(content, options);
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
const colorCap = getColorCapability();
|
|
1583
|
+
const output = renderBox(content, options, colorCap);
|
|
1584
|
+
process.stderr.write(output + '\n');
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
/**
|
|
1588
|
+
* Renders an array of objects as a formatted ASCII table.
|
|
1589
|
+
* Note: This is distinct from the existing table() method which uses console.table.
|
|
1590
|
+
*
|
|
1591
|
+
* @param {Record<string, unknown>[]} rows - Array of row objects
|
|
1592
|
+
* @param {ITableOptions} options - Table rendering options
|
|
1593
|
+
*
|
|
1594
|
+
* @example
|
|
1595
|
+
* logger.cliTable([
|
|
1596
|
+
* { provider: 'Groq', status: 'Available', model: 'llama-3.3-70b' },
|
|
1597
|
+
* { provider: 'Gemini', status: 'Configured', model: 'gemini-2.5-flash' },
|
|
1598
|
+
* ]);
|
|
1599
|
+
*
|
|
1600
|
+
* @since 5.0.0
|
|
1601
|
+
*/
|
|
1602
|
+
cliTable(rows: Record<string, unknown>[], options?: ITableOptions): void {
|
|
1603
|
+
if (!this._showPrimitives) return;
|
|
1604
|
+
if (!isRunningInTerminal()) {
|
|
1605
|
+
this.getServerFallback().cliTable(rows, options);
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
const colorCap = getColorCapability();
|
|
1609
|
+
const output = renderTable(rows, options, colorCap);
|
|
1610
|
+
process.stderr.write(output + '\n');
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
/**
|
|
1614
|
+
* Creates a spinner handle for showing progress during async operations.
|
|
1615
|
+
* Returns a NoopSpinner in non-TTY environments.
|
|
1616
|
+
*
|
|
1617
|
+
* @param {string} message - Initial spinner text
|
|
1618
|
+
* @returns {ISpinnerHandle} Spinner controller
|
|
1619
|
+
*
|
|
1620
|
+
* @example
|
|
1621
|
+
* const s = logger.spinner('Analyzing repository...');
|
|
1622
|
+
* s.start();
|
|
1623
|
+
* await analyzeRepo();
|
|
1624
|
+
* s.succeed('Analysis complete (1.2s)');
|
|
1625
|
+
*
|
|
1626
|
+
* @since 5.0.0
|
|
1627
|
+
*/
|
|
1628
|
+
spinner(message: string): ISpinnerHandle {
|
|
1629
|
+
if (!isRunningInTerminal() || this.config.outputMode === 'silent') {
|
|
1630
|
+
return new NoopSpinner(message, this);
|
|
1631
|
+
}
|
|
1632
|
+
return new SpinnerManager(message, this.config, this);
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
/**
|
|
1636
|
+
* Sets the CLI verbosity level, controlling both log verbosity and primitive visibility
|
|
1637
|
+
*
|
|
1638
|
+
* @param {CLILogLevel} level - CLI log level
|
|
1639
|
+
*
|
|
1640
|
+
* @example
|
|
1641
|
+
* logger.setCLILevel('quiet'); // Only errors, no CLI primitives
|
|
1642
|
+
* logger.setCLILevel('verbose'); // Debug logs + all CLI primitives
|
|
1643
|
+
*
|
|
1644
|
+
* @since 5.0.0
|
|
1645
|
+
*/
|
|
1646
|
+
setCLILevel(level: CLILogLevel): void {
|
|
1647
|
+
const mapping = CLI_LEVEL_MAP[level];
|
|
1648
|
+
this.setVerbosity(mapping.verbosity);
|
|
1649
|
+
this._showPrimitives = mapping.showPrimitives;
|
|
1650
|
+
this.config.cliLevel = level;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
/**
|
|
1654
|
+
* Returns the current CLI log level
|
|
1655
|
+
* @returns {CLILogLevel} Current CLI log level
|
|
1656
|
+
* @since 5.0.0
|
|
1657
|
+
*/
|
|
1658
|
+
get cliLevel(): CLILogLevel {
|
|
1659
|
+
return this.config.cliLevel ?? 'normal';
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
/** Lazily creates the server fallback instance @private */
|
|
1663
|
+
private getServerFallback(): ServerFallback {
|
|
1664
|
+
if (!this._serverFallback) {
|
|
1665
|
+
this._serverFallback = new ServerFallback(this);
|
|
1666
|
+
}
|
|
1667
|
+
return this._serverFallback;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1465
1670
|
// ===== OUTPUT WRITER SYSTEM =====
|
|
1466
1671
|
|
|
1467
1672
|
/**
|