@lakindu_perera/toren 1.0.3 → 1.0.4
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/README.md +28 -1
- package/bin/toren.js +33 -10
- package/package.json +1 -1
- package/src/focused-output.js +71 -0
- package/src/renderers/console-renderer.js +31 -3
package/README.md
CHANGED
|
@@ -62,6 +62,12 @@ toren --format markdown > PROJECT_REPORT.md
|
|
|
62
62
|
toren --format html > report.html
|
|
63
63
|
toren --format json > scan.json
|
|
64
64
|
|
|
65
|
+
# Focused Output Modes (Mutually Exclusive)
|
|
66
|
+
toren --project-type
|
|
67
|
+
toren --frameworks
|
|
68
|
+
toren --entry-points
|
|
69
|
+
toren --structure
|
|
70
|
+
|
|
65
71
|
# Lifecycle & Help Commands
|
|
66
72
|
toren --help
|
|
67
73
|
toren --version
|
|
@@ -74,6 +80,10 @@ toren --uninstall
|
|
|
74
80
|
| Flag | Description |
|
|
75
81
|
|------|-------------|
|
|
76
82
|
| `[path]` | Directory to scan. Defaults to the current directory (`.`). |
|
|
83
|
+
| `--project-type` | Show detected project type only. |
|
|
84
|
+
| `--frameworks` | Show detected frameworks only. |
|
|
85
|
+
| `--entry-points` | Show detected entry points only. |
|
|
86
|
+
| `--structure` | Show repository structure only. |
|
|
77
87
|
| `--format <type>` | Output format: `console` (default), `json`, `markdown`, `html`. |
|
|
78
88
|
| `--include-hidden` | Include hidden files and dot-directories in the scan. |
|
|
79
89
|
| `--max-files <N>` | Override the default 50,000-file scan limit. |
|
|
@@ -83,16 +93,33 @@ toren --uninstall
|
|
|
83
93
|
| `--uninstall` | Safely remove Toren from the global npm environment. |
|
|
84
94
|
|
|
85
95
|
> **Note:** `--format md` is not a valid alias. Use `--format markdown` in full.
|
|
96
|
+
> **Note:** Focused output flags (`--project-type`, `--frameworks`, `--entry-points`, `--structure`) are mutually exclusive.
|
|
86
97
|
|
|
87
98
|
---
|
|
88
99
|
|
|
89
100
|
## Output Examples
|
|
90
101
|
|
|
102
|
+
### Focused Output Example
|
|
103
|
+
Sometimes you only need a specific piece of intelligence for use in a script or a quick lookup. Use the focused output flags to bypass the full report:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
$ toren --project-type
|
|
107
|
+
Project Type: Node.js / JavaScript
|
|
108
|
+
|
|
109
|
+
$ toren --frameworks
|
|
110
|
+
Frameworks:
|
|
111
|
+
- React
|
|
112
|
+
|
|
113
|
+
$ toren --entry-points
|
|
114
|
+
Entry Points:
|
|
115
|
+
- src/main.tsx
|
|
116
|
+
```
|
|
117
|
+
|
|
91
118
|
### Console Output Example
|
|
92
119
|
The default `console` format renders a beautiful summary directly in your terminal:
|
|
93
120
|
|
|
94
121
|
```text
|
|
95
|
-
Toren v1.0.
|
|
122
|
+
Toren v1.0.4 — Codebase Onboarding Intelligence
|
|
96
123
|
|
|
97
124
|
🔍 Project Summary
|
|
98
125
|
────────────────────────────────────────────────────────────────────────────────
|
package/bin/toren.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import { createRequire } from 'node:module';
|
|
26
26
|
import { scan } from '../src/scanner/scan.js';
|
|
27
27
|
import renderers from '../src/renderers/index.js';
|
|
28
|
+
import { getFocusedModeInfo, renderFocusedMode, FOCUSED_FLAGS } from '../src/focused-output.js';
|
|
28
29
|
import { runDoctor, runUninstall } from '../src/lifecycle.js';
|
|
29
30
|
|
|
30
31
|
const require = createRequire(import.meta.url);
|
|
@@ -44,14 +45,20 @@ function printHelp() {
|
|
|
44
45
|
const formatList = SUPPORTED_FORMATS.map(f => ` ${f}`).join('\n');
|
|
45
46
|
console.log(`
|
|
46
47
|
\x1b[1mUsage:\x1b[0m
|
|
47
|
-
toren [path]
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
toren [path] [options]
|
|
49
|
+
|
|
50
|
+
\x1b[1mOptions:\x1b[0m
|
|
51
|
+
--project-type Show detected project type only
|
|
52
|
+
--frameworks Show detected frameworks only
|
|
53
|
+
--entry-points Show detected entry points only
|
|
54
|
+
--structure Show repository structure only
|
|
55
|
+
--format <type> Output as console, json, markdown, or html
|
|
56
|
+
--include-hidden Include hidden files and folders
|
|
57
|
+
--max-files <n> Set scan file limit
|
|
58
|
+
--help Show this help message
|
|
59
|
+
--version Show version number
|
|
60
|
+
--doctor Run CLI diagnostics
|
|
61
|
+
--uninstall Remove Toren global installation
|
|
55
62
|
|
|
56
63
|
\x1b[1mOutput Formats:\x1b[0m
|
|
57
64
|
${formatList}
|
|
@@ -140,6 +147,16 @@ function parseArgs() {
|
|
|
140
147
|
format = 'json';
|
|
141
148
|
}
|
|
142
149
|
|
|
150
|
+
// ── Focused Output Flags ────────────────────────────────────────────────
|
|
151
|
+
const focusedInfo = getFocusedModeInfo(args);
|
|
152
|
+
|
|
153
|
+
if (focusedInfo.error) {
|
|
154
|
+
console.error(focusedInfo.message);
|
|
155
|
+
return { action: 'exit', code: 1 };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const focusedMode = focusedInfo.mode;
|
|
159
|
+
|
|
143
160
|
// ── Hidden files ────────────────────────────────────────────────────────
|
|
144
161
|
const includeHidden = args.includes('--include-hidden');
|
|
145
162
|
|
|
@@ -184,6 +201,7 @@ function parseArgs() {
|
|
|
184
201
|
'--uninstall',
|
|
185
202
|
'--format',
|
|
186
203
|
'--json',
|
|
204
|
+
...FOCUSED_FLAGS,
|
|
187
205
|
'--include-hidden',
|
|
188
206
|
'--max-files',
|
|
189
207
|
]);
|
|
@@ -198,7 +216,7 @@ function parseArgs() {
|
|
|
198
216
|
return { action: 'exit', code: 1 };
|
|
199
217
|
}
|
|
200
218
|
|
|
201
|
-
return { action: 'scan', target, format, includeHidden, maxFiles };
|
|
219
|
+
return { action: 'scan', target, format, includeHidden, maxFiles, focusedMode };
|
|
202
220
|
}
|
|
203
221
|
|
|
204
222
|
// ---------------------------------------------------------------------------
|
|
@@ -249,7 +267,12 @@ function assertValidFormat(format) {
|
|
|
249
267
|
includeHidden: parsed.includeHidden,
|
|
250
268
|
maxFiles: parsed.maxFiles,
|
|
251
269
|
});
|
|
252
|
-
|
|
270
|
+
|
|
271
|
+
if (parsed.focusedMode) {
|
|
272
|
+
renderFocusedMode(parsed.focusedMode, result);
|
|
273
|
+
} else {
|
|
274
|
+
render(result, { cwd: process.cwd() });
|
|
275
|
+
}
|
|
253
276
|
} catch (err) {
|
|
254
277
|
// Render errors in the requested format where possible.
|
|
255
278
|
if (parsed.format === 'json') {
|
package/package.json
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Focused output modes handling for Toren CLI.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { renderStructure } from './renderers/console-renderer.js';
|
|
6
|
+
|
|
7
|
+
export const FOCUSED_FLAGS = [
|
|
8
|
+
'--project-type',
|
|
9
|
+
'--frameworks',
|
|
10
|
+
'--entry-points',
|
|
11
|
+
'--structure'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Validates focused flags in the provided arguments.
|
|
16
|
+
*
|
|
17
|
+
* @param {string[]} args Process arguments
|
|
18
|
+
* @returns {{ error: boolean, message?: string, mode?: string|null }}
|
|
19
|
+
*/
|
|
20
|
+
export function getFocusedModeInfo(args) {
|
|
21
|
+
const activeFlags = FOCUSED_FLAGS.filter(flag => args.includes(flag));
|
|
22
|
+
|
|
23
|
+
if (activeFlags.length > 1) {
|
|
24
|
+
return {
|
|
25
|
+
error: true,
|
|
26
|
+
message: '\x1b[31mError: focused output flags are mutually exclusive. Please use only one of:\x1b[0m\n' +
|
|
27
|
+
FOCUSED_FLAGS.map(f => ` ${f}`).join('\n') + '\n'
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
error: false,
|
|
33
|
+
mode: activeFlags[0] || null
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Renders the scan result based on the active focused mode.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} mode Active focused mode flag
|
|
41
|
+
* @param {import('./scanner/scan.js').ScanResult} result
|
|
42
|
+
*/
|
|
43
|
+
export function renderFocusedMode(mode, result) {
|
|
44
|
+
switch (mode) {
|
|
45
|
+
case '--project-type':
|
|
46
|
+
console.log(`Project Type: ${result.projectType}`);
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case '--frameworks':
|
|
50
|
+
if (!result.projectType || result.projectType === 'Unknown') {
|
|
51
|
+
console.log('Frameworks: None detected');
|
|
52
|
+
} else {
|
|
53
|
+
console.log('Frameworks:');
|
|
54
|
+
console.log(`- ${result.projectType}`);
|
|
55
|
+
}
|
|
56
|
+
break;
|
|
57
|
+
|
|
58
|
+
case '--entry-points':
|
|
59
|
+
if (!result.entryPoints || result.entryPoints.length === 0) {
|
|
60
|
+
console.log('Entry Points: None detected');
|
|
61
|
+
} else {
|
|
62
|
+
console.log('Entry Points:');
|
|
63
|
+
result.entryPoints.forEach(ep => console.log(`- ${ep}`));
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
|
|
67
|
+
case '--structure':
|
|
68
|
+
renderStructure(result);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -99,8 +99,11 @@ function row(label, value, ...valueCodes) {
|
|
|
99
99
|
* @param {string} prefix - Accumulated indentation
|
|
100
100
|
* @param {boolean} isLast - Whether this is the last sibling
|
|
101
101
|
* @param {{ count: number, maxReached: boolean }} counter - Shared mutable file counter
|
|
102
|
+
* @param {number} limit - Max files to render
|
|
103
|
+
* @param {number} depth - Current depth
|
|
104
|
+
* @param {number} maxDepth - Max recursion depth
|
|
102
105
|
*/
|
|
103
|
-
function renderTree(node, prefix, isLast, counter, depth = 0, maxDepth = 4) {
|
|
106
|
+
function renderTree(node, prefix, isLast, counter, limit = PREVIEW_LIMIT, depth = 0, maxDepth = 4) {
|
|
104
107
|
if (counter.maxReached) return;
|
|
105
108
|
if (depth >= maxDepth) return;
|
|
106
109
|
|
|
@@ -117,7 +120,7 @@ function renderTree(node, prefix, isLast, counter, depth = 0, maxDepth = 4) {
|
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
for (let i = 0; i < children.length; i++) {
|
|
120
|
-
if (counter.count >=
|
|
123
|
+
if (counter.count >= limit) {
|
|
121
124
|
console.log(`${prefix}${extension}└── ${paint('...', C.dim)}`);
|
|
122
125
|
counter.maxReached = true;
|
|
123
126
|
break;
|
|
@@ -125,7 +128,7 @@ function renderTree(node, prefix, isLast, counter, depth = 0, maxDepth = 4) {
|
|
|
125
128
|
// Check if this child will be the last one we render due to limits
|
|
126
129
|
let willBeLast = i === children.length - 1;
|
|
127
130
|
|
|
128
|
-
renderTree(children[i], prefix + extension, willBeLast, counter, depth + 1, maxDepth);
|
|
131
|
+
renderTree(children[i], prefix + extension, willBeLast, counter, limit, depth + 1, maxDepth);
|
|
129
132
|
if (counter.maxReached) break;
|
|
130
133
|
}
|
|
131
134
|
} else {
|
|
@@ -228,3 +231,28 @@ export function render(result, options = {}) {
|
|
|
228
231
|
console.log(paint(' ✅ Scan complete.', C.green));
|
|
229
232
|
console.log('');
|
|
230
233
|
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Render only the project structure for the --structure flag.
|
|
237
|
+
*
|
|
238
|
+
* @param {import('../scanner/scan.js').ScanResult} result
|
|
239
|
+
*/
|
|
240
|
+
export function renderStructure(result) {
|
|
241
|
+
const { tree, flatFiles } = result;
|
|
242
|
+
|
|
243
|
+
console.log(paint('Project Structure:', C.bold, C.white));
|
|
244
|
+
console.log(paint(`${tree.name || '.'}/`, C.bold, C.blue));
|
|
245
|
+
|
|
246
|
+
const counter = { count: 0, maxReached: false };
|
|
247
|
+
const children = tree.children ?? [];
|
|
248
|
+
const limit = flatFiles.length; // No preview limit for focused --structure
|
|
249
|
+
|
|
250
|
+
for (let i = 0; i < children.length; i++) {
|
|
251
|
+
if (counter.count >= limit) {
|
|
252
|
+
console.log(`└── ${paint('...', C.dim)}`);
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
renderTree(children[i], '', i === children.length - 1, counter, limit, 0, Infinity);
|
|
256
|
+
if (counter.maxReached) break;
|
|
257
|
+
}
|
|
258
|
+
}
|