@lakindu_perera/toren 1.0.4 → 1.0.7

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 CHANGED
@@ -67,6 +67,8 @@ toren --project-type
67
67
  toren --frameworks
68
68
  toren --entry-points
69
69
  toren --structure
70
+ toren --configs
71
+ toren --scripts
70
72
 
71
73
  # Lifecycle & Help Commands
72
74
  toren --help
@@ -75,66 +77,54 @@ toren --doctor
75
77
  toren --uninstall
76
78
  ```
77
79
 
78
- ### All Flags
80
+ ### CLI Reference
79
81
 
80
- | Flag | Description |
81
- |------|-------------|
82
+ | Command / Flag | Description |
83
+ |----------------|-------------|
82
84
  | `[path]` | Directory to scan. Defaults to the current directory (`.`). |
83
85
  | `--project-type` | Show detected project type only. |
84
86
  | `--frameworks` | Show detected frameworks only. |
85
87
  | `--entry-points` | Show detected entry points only. |
86
88
  | `--structure` | Show repository structure only. |
89
+ | `--configs` | Show detected project configuration files. |
90
+ | `--scripts` | Show available package scripts only. |
87
91
  | `--format <type>` | Output format: `console` (default), `json`, `markdown`, `html`. |
88
92
  | `--include-hidden` | Include hidden files and dot-directories in the scan. |
89
- | `--max-files <N>` | Override the default 50,000-file scan limit. |
90
- | `--help` / `-h` | Show usage information. |
91
- | `--version` / `-V` | Print the installed version number. |
93
+ | `--max-files <n>` | Override the default 50,000-file scan limit. |
94
+ | `--help`, `-h` | Show usage and help message. |
95
+ | `--version`, `-v` | Print the installed version number. |
92
96
  | `--doctor` | Diagnose the global installation health. |
93
97
  | `--uninstall` | Safely remove Toren from the global npm environment. |
94
98
 
95
99
  > **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.
100
+ > **Note:** Focused output flags (`--project-type`, `--frameworks`, `--entry-points`, `--structure`, `--configs`, `--scripts`) are mutually exclusive.
97
101
 
98
102
  ---
99
103
 
100
- ## Output Examples
104
+ ## Screenshots & Output Examples
101
105
 
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:
106
+ ### Console Output Example
107
+ The default `console` format renders a beautiful summary directly in your terminal:
104
108
 
105
- ```bash
106
- $ toren --project-type
107
- Project Type: Node.js / JavaScript
109
+ ```text
110
+ Toren v1.0.6 — Codebase Onboarding Intelligence
108
111
 
109
- $ toren --frameworks
110
- Frameworks:
111
- - React
112
+ Project Summary
113
+ ───────────────
112
114
 
113
- $ toren --entry-points
114
- Entry Points:
115
- - src/main.tsx
116
- ```
115
+ Path: ./my-react-app
116
+ Project type: React
117
+ Total files: 32
118
+ Total folders: 6
117
119
 
118
- ### Console Output Example
119
- The default `console` format renders a beautiful summary directly in your terminal:
120
+ Entry Points
121
+ ────────────
122
+
123
+ src/main.tsx
124
+
125
+ Folder Structure (first 20 files)
126
+ ──────────────────────────────────
120
127
 
121
- ```text
122
- Toren v1.0.4 — Codebase Onboarding Intelligence
123
-
124
- 🔍 Project Summary
125
- ────────────────────────────────────────────────────────────────────────────────
126
- Path: ./my-react-app
127
- Project type: React
128
- Total files: 32
129
- Total folders: 6
130
- Scan duration: 4 ms
131
-
132
- 🚪 Entry Points
133
- ────────────────────────────────────────────────────────────────────────────────
134
- → src/main.tsx
135
-
136
- 📁 Folder Structure (first 20 files)
137
- ────────────────────────────────────────────────────────────────────────────────
138
128
  my-react-app/
139
129
  ├── public/
140
130
  │ └── vite.svg
@@ -148,10 +138,46 @@ my-react-app/
148
138
  ├── index.html
149
139
  ├── package.json
150
140
  └── vite.config.ts
151
- … and 21 more file(s) not shown
141
+ … and 21 more file(s) not shown
152
142
 
153
- ────────────────────────────────────────────────────────────────────────────────
154
- ✅ Scan complete.
143
+ Scan completed in 4 ms
144
+ ```
145
+
146
+ ### Focused Output Examples
147
+ 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:
148
+
149
+ ```bash
150
+ $ toren --project-type
151
+ Project Type
152
+ ────────────
153
+
154
+ Node.js / JavaScript
155
+
156
+ $ toren --frameworks
157
+ Frameworks
158
+ ──────────
159
+
160
+ React
161
+
162
+ $ toren --entry-points
163
+ Entry Points
164
+ ────────────
165
+
166
+ src/main.tsx
167
+
168
+ $ toren --configs
169
+ Configuration Files
170
+ ───────────────────
171
+
172
+ package.json
173
+ vite.config.ts
174
+
175
+ $ toren --scripts
176
+ Package Scripts
177
+ ───────────────
178
+
179
+ start vite
180
+ test vitest
155
181
  ```
156
182
 
157
183
  ### JSON Output Example
@@ -190,6 +216,17 @@ Generate machine-readable output for scripts, toolchains, or AI context windows
190
216
 
191
217
  ---
192
218
 
219
+ ## Release Notes
220
+
221
+ ### v1.0.6 - CLI Experience Update
222
+ - **Redesigned CLI Output**: Completely revamped the console layout to use minimal typography, bold section titles, and dynamic divider lines matching the title width.
223
+ - **Improved Error Handling**: Transformed raw exceptions into user-friendly error messages outlining the issue and potential fixes, ensuring consistent exit codes.
224
+ - **Enhanced Focused Modes**: Focused output flags (`--configs`, `--entry-points`, `--structure`, etc.) now strictly mirror the design tokens of the full console renderer, providing identical spacing and layouts.
225
+ - **Streamlined Help & Version**: The `--help` interface was fully redesigned for faster reading, and `-v` / `--version` flags were added to output the exact binary version directly from `package.json`.
226
+ - **Accurate Timing Metrics**: Scan duration logic was improved to utilize native timing APIs, precisely measuring execution and printing results natively as "Scan completed in X ms" without clogging the project summary.
227
+
228
+ ---
229
+
193
230
  ## Architecture
194
231
 
195
232
  Toren's internal architecture emphasizes modular design, separation of concerns, and a strict **zero dependency** philosophy.
@@ -236,12 +273,12 @@ Contributions to improve this codebase analyzer CLI are always welcome!
236
273
 
237
274
  ---
238
275
 
239
- ## 📄 License
276
+ ## License
240
277
 
241
278
  Distributed under the MIT License. See `LICENSE` for more information.
242
279
 
243
280
  ---
244
281
 
245
- ## 👨‍💻 Author
282
+ ## Author
246
283
 
247
284
  Built with by **[Lakindu Perera](https://github.com/lakindudev)**.
package/bin/toren.js CHANGED
@@ -38,41 +38,56 @@ const DEFAULT_FORMAT = 'console';
38
38
  const SUPPORTED_FORMATS = Object.keys(renderers);
39
39
 
40
40
  // ---------------------------------------------------------------------------
41
- // Help
41
+ // Helpers
42
42
  // ---------------------------------------------------------------------------
43
43
 
44
+ function printError(title, message, detailLabel, detailValue) {
45
+ console.error(`\x1b[31m✖ ${title}\x1b[0m\n`);
46
+ console.error(`${message}\n`);
47
+ if (detailLabel && detailValue) {
48
+ console.error(`${detailLabel}:\n`);
49
+ console.error(`${detailValue}\n`);
50
+ }
51
+ }
52
+
44
53
  function printHelp() {
45
- const formatList = SUPPORTED_FORMATS.map(f => ` ${f}`).join('\n');
54
+ const formatList = SUPPORTED_FORMATS.map(f => {
55
+ const suffix = f === DEFAULT_FORMAT ? ' (default)' : '';
56
+ return ` --format ${f.padEnd(10)}${suffix}`;
57
+ }).join('\n');
58
+
46
59
  console.log(`
47
- \x1b[1mUsage:\x1b[0m
60
+ \x1b[1mToren\x1b[0m v${pkg.version}
61
+ Fast Repository Discovery CLI
62
+
63
+ \x1b[1mUSAGE\x1b[0m
48
64
  toren [path] [options]
49
65
 
50
- \x1b[1mOptions:\x1b[0m
66
+ \x1b[1mCOMMANDS\x1b[0m
51
67
  --project-type Show detected project type only
52
68
  --frameworks Show detected frameworks only
53
69
  --entry-points Show detected entry points only
54
70
  --structure Show repository structure only
55
- --format <type> Output as console, json, markdown, or html
71
+ --configs Show detected project configuration files
72
+ --scripts Show available package scripts only
56
73
  --include-hidden Include hidden files and folders
57
74
  --max-files <n> Set scan file limit
58
- --help Show this help message
59
- --version Show version number
60
75
  --doctor Run CLI diagnostics
61
76
  --uninstall Remove Toren global installation
77
+ --help Show this help message
78
+ --version Show version number
62
79
 
63
- \x1b[1mOutput Formats:\x1b[0m
80
+ \x1b[1mOUTPUT FORMATS\x1b[0m
64
81
  ${formatList}
65
82
 
66
- console is the default.
67
-
68
- \x1b[1mExamples:\x1b[0m
83
+ \x1b[1mEXAMPLES\x1b[0m
69
84
  toren . Scan the current directory
70
85
  toren ./my-project Scan a specific project folder
71
86
  toren --format json . Output results as JSON
72
87
  toren --format markdown . > out.md Save a Markdown report to a file
73
88
  toren --format html . > out.html Save an HTML report to a file
74
- toren --include-hidden . Include hidden dot-files in scan
75
- toren --max-files 100000 . Override the 50k file scan limit
89
+ toren . --configs Show project configuration files
90
+ toren . --frameworks Show detected frameworks
76
91
  `);
77
92
  }
78
93
 
@@ -108,7 +123,7 @@ function parseArgs() {
108
123
  }
109
124
 
110
125
  if (args.includes('--version') || args.includes('-V') || args.includes('-v')) {
111
- console.log(pkg.version);
126
+ console.log(`Toren ${pkg.version}`);
112
127
  return { action: 'exit', code: 0 };
113
128
  }
114
129
 
@@ -133,13 +148,12 @@ function parseArgs() {
133
148
  const nextToken = args[formatIdx + 1];
134
149
  // If the next token is missing or starts with '-', the user omitted the value.
135
150
  if (nextToken === undefined || nextToken.startsWith('-')) {
136
- console.error('');
137
- console.error('\x1b[31m --format requires a value.\x1b[0m');
138
- console.error('');
139
- console.error(` Supported formats: ${SUPPORTED_FORMATS.join(', ')}`);
140
- console.error('');
141
- console.error(' Run \x1b[36mtoren --help\x1b[0m for usage.');
142
- console.error('');
151
+ printError(
152
+ 'Missing value',
153
+ 'The --format flag requires a valid output format.',
154
+ 'Supported formats',
155
+ SUPPORTED_FORMATS.join(', ')
156
+ );
143
157
  return { action: 'exit', code: 1 };
144
158
  }
145
159
  format = nextToken;
@@ -151,7 +165,7 @@ function parseArgs() {
151
165
  const focusedInfo = getFocusedModeInfo(args);
152
166
 
153
167
  if (focusedInfo.error) {
154
- console.error(focusedInfo.message);
168
+ printError(focusedInfo.title, focusedInfo.message, focusedInfo.detailLabel, focusedInfo.detailValue);
155
169
  return { action: 'exit', code: 1 };
156
170
  }
157
171
 
@@ -174,17 +188,22 @@ function parseArgs() {
174
188
  if (maxFilesIdx !== -1) {
175
189
  const rawVal = args[maxFilesIdx + 1];
176
190
  if (rawVal === undefined || rawVal.startsWith('-')) {
177
- console.error('');
178
- console.error('\x1b[31m --max-files requires a numeric value.\x1b[0m');
179
- console.error(' Example: toren --max-files 100000');
180
- console.error('');
191
+ printError(
192
+ 'Missing value',
193
+ 'The --max-files flag requires a numeric value.',
194
+ 'Example',
195
+ 'toren --max-files 100000'
196
+ );
181
197
  return { action: 'exit', code: 1 };
182
198
  }
183
199
  maxFiles = parseInt(rawVal, 10);
184
200
  if (isNaN(maxFiles) || maxFiles < 1) {
185
- console.error('');
186
- console.error(`\x1b[31m --max-files must be a positive integer, got: ${rawVal}\x1b[0m`);
187
- console.error('');
201
+ printError(
202
+ 'Invalid value',
203
+ 'The --max-files flag must be a positive integer.',
204
+ 'Provided value',
205
+ rawVal
206
+ );
188
207
  return { action: 'exit', code: 1 };
189
208
  }
190
209
  consumedValues.add(rawVal);
@@ -211,8 +230,12 @@ function parseArgs() {
211
230
  );
212
231
 
213
232
  if (unknownFlag) {
214
- console.error(`\x1b[31m Unknown flag: ${unknownFlag}\x1b[0m`);
215
- console.error(` Run \x1b[36mtoren --help\x1b[0m for usage.\n`);
233
+ printError(
234
+ 'Unknown option',
235
+ 'An unrecognized flag was provided.',
236
+ 'Flag',
237
+ unknownFlag
238
+ );
216
239
  return { action: 'exit', code: 1 };
217
240
  }
218
241
 
@@ -232,16 +255,12 @@ function parseArgs() {
232
255
  function assertValidFormat(format) {
233
256
  if (renderers[format]) return;
234
257
 
235
- const list = SUPPORTED_FORMATS.map(f => ` • ${f}`).join('\n');
236
- console.error('');
237
- console.error(`\x1b[31m Unknown output format: ${format}\x1b[0m`);
238
- console.error('');
239
- console.error(' Supported formats:');
240
- console.error('');
241
- console.error(list);
242
- console.error('');
243
- console.error(' Run \x1b[36mtoren --help\x1b[0m for usage.');
244
- console.error('');
258
+ printError(
259
+ 'Unsupported output format',
260
+ 'The requested output format is not supported.',
261
+ 'Format',
262
+ format
263
+ );
245
264
  process.exit(1);
246
265
  }
247
266
 
@@ -278,9 +297,11 @@ function assertValidFormat(format) {
278
297
  if (parsed.format === 'json') {
279
298
  console.error(JSON.stringify({ error: err.message }, null, 2));
280
299
  } else {
281
- console.error('');
282
- console.error(`\x1b[31m ❌ Error: ${err.message}\x1b[0m`);
283
- console.error('');
300
+ if (err.title) {
301
+ printError(err.title, err.message, err.detailLabel, err.detailValue);
302
+ } else {
303
+ printError('Scan failed', err.message);
304
+ }
284
305
  }
285
306
  process.exit(1);
286
307
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lakindu_perera/toren",
3
- "version": "1.0.4",
3
+ "version": "1.0.7",
4
4
  "description": "A powerful codebase scanner CLI tool for project analysis, framework detection, and understanding repository structure instantly.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,6 +14,7 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "start": "node bin/toren.js",
17
+ "test": "node --test",
17
18
  "lint": "node --check bin/toren.js src/scanner/scan.js src/lifecycle.js src/renderers/index.js src/renderers/console-renderer.js src/renderers/json-renderer.js src/renderers/markdown-renderer.js src/renderers/html-renderer.js"
18
19
  },
19
20
  "keywords": [
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @fileoverview Configuration file detector
3
+ */
4
+
5
+ /**
6
+ * Detects common configuration files in the root of the repository.
7
+ *
8
+ * @param {string[]} flatFiles - Array of relative file paths from the scanner
9
+ * @returns {{ configs: string[] }}
10
+ */
11
+ export function detectConfigs(flatFiles) {
12
+ const configPatterns = [
13
+ // Package
14
+ /^package\.json$/,
15
+ /^package-lock\.json$/,
16
+ /^pnpm-lock\.yaml$/,
17
+ /^yarn\.lock$/,
18
+ /^bun\.lockb$/,
19
+
20
+ // TypeScript
21
+ /^tsconfig\.json$/,
22
+ /^jsconfig\.json$/,
23
+
24
+ // Frontend
25
+ /^vite\.config\.[a-zA-Z0-9]+$/,
26
+ /^next\.config\.[a-zA-Z0-9]+$/,
27
+ /^nuxt\.config\.[a-zA-Z0-9]+$/,
28
+ /^astro\.config\.[a-zA-Z0-9]+$/,
29
+ /^angular\.json$/,
30
+
31
+ // Build
32
+ /^webpack\.config\.[a-zA-Z0-9]+$/,
33
+ /^rollup\.config\.[a-zA-Z0-9]+$/,
34
+ /^turbo\.json$/,
35
+ /^nx\.json$/,
36
+
37
+ // Styling
38
+ /^tailwind\.config\.[a-zA-Z0-9]+$/,
39
+ /^postcss\.config\.[a-zA-Z0-9]+$/,
40
+
41
+ // Lint
42
+ /^eslint\.config\.[a-zA-Z0-9]+$/,
43
+ /^\.eslintrc.*$/,
44
+ /^prettier\.config\.[a-zA-Z0-9]+$/,
45
+ /^\.prettierrc.*$/,
46
+
47
+ // Backend
48
+ /^pom\.xml$/,
49
+ /^build\.gradle$/,
50
+ /^build\.gradle\.kts$/,
51
+
52
+ // Languages
53
+ /^requirements\.txt$/,
54
+ /^pyproject\.toml$/,
55
+ /^Cargo\.toml$/,
56
+ /^go\.mod$/,
57
+
58
+ // Deployment
59
+ /^Dockerfile$/,
60
+ /^docker-compose\.ya?ml$/
61
+ ];
62
+
63
+ const matchedSet = new Set();
64
+
65
+ for (const file of flatFiles) {
66
+ // Ensure we only match files at the root of the repository
67
+ if (file.includes('/')) continue;
68
+
69
+ for (const pattern of configPatterns) {
70
+ if (pattern.test(file)) {
71
+ matchedSet.add(file);
72
+ break; // Stop checking patterns once a match is found
73
+ }
74
+ }
75
+ }
76
+
77
+ // Convert Set to Array and sort alphabetically
78
+ const configs = Array.from(matchedSet).sort();
79
+
80
+ return { configs };
81
+ }
@@ -0,0 +1,32 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ /**
5
+ * Detects npm/package scripts from package.json in the project root.
6
+ *
7
+ * @param {string} rootPath - The absolute path of the scanned root
8
+ * @returns {{ scripts: Array<{name: string, command: string}> }}
9
+ */
10
+ export function detectScripts(rootPath) {
11
+ const scripts = [];
12
+ const pkgPath = path.join(rootPath, 'package.json');
13
+
14
+ try {
15
+ if (fs.existsSync(pkgPath)) {
16
+ const content = fs.readFileSync(pkgPath, 'utf8');
17
+ const pkg = JSON.parse(content);
18
+
19
+ if (pkg.scripts && typeof pkg.scripts === 'object') {
20
+ for (const [name, command] of Object.entries(pkg.scripts)) {
21
+ if (typeof command === 'string') {
22
+ scripts.push({ name, command });
23
+ }
24
+ }
25
+ }
26
+ }
27
+ } catch (error) {
28
+ // Return empty scripts on malformed or unreadable package.json
29
+ }
30
+
31
+ return { scripts };
32
+ }
@@ -1,14 +1,40 @@
1
1
  /**
2
- * @fileoverview Focused output modes handling for Toren CLI.
2
+ * @fileoverview Toren Focused Output Mode Handler
3
+ *
4
+ * Handles the six focused output flags:
5
+ * --project-type --frameworks --entry-points
6
+ * --structure --configs --scripts
7
+ *
8
+ * Design contract:
9
+ * - Each flag renders exactly one section to stdout using the console visual
10
+ * style (ANSI colours, section header + divider).
11
+ * - Empty-state messages are canonical strings declared in EMPTY below.
12
+ * They must end with a period and stay in sync with console-renderer.js.
13
+ * - No business logic. All data comes from the ScanResult passed in.
14
+ * - Stateless: renderFocusedMode() may be called multiple times safely.
3
15
  */
4
16
 
5
17
  import { renderStructure } from './renderers/console-renderer.js';
6
18
 
19
+ // ---------------------------------------------------------------------------
20
+ // Canonical empty-state messages
21
+ // Keep these in sync with the equivalent strings in console-renderer.js.
22
+ // ---------------------------------------------------------------------------
23
+
24
+ const EMPTY = {
25
+ frameworks: 'No frameworks detected.',
26
+ entryPoints: 'No entry points detected.',
27
+ configs: 'No configuration files detected.',
28
+ scripts: 'No package scripts detected.',
29
+ };
30
+
7
31
  export const FOCUSED_FLAGS = [
8
32
  '--project-type',
9
33
  '--frameworks',
10
34
  '--entry-points',
11
- '--structure'
35
+ '--structure',
36
+ '--configs',
37
+ '--scripts'
12
38
  ];
13
39
 
14
40
  /**
@@ -23,8 +49,10 @@ export function getFocusedModeInfo(args) {
23
49
  if (activeFlags.length > 1) {
24
50
  return {
25
51
  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'
52
+ title: 'Conflicting options',
53
+ message: 'Focused output flags are mutually exclusive.',
54
+ detailLabel: 'Provided flags',
55
+ detailValue: activeFlags.join(', ')
28
56
  };
29
57
  }
30
58
 
@@ -34,6 +62,37 @@ export function getFocusedModeInfo(args) {
34
62
  };
35
63
  }
36
64
 
65
+ /**
66
+ * Print a bold-white section title followed by a dim matched-length divider
67
+ * and a blank line — same visual pattern as console-renderer.js's section().
68
+ *
69
+ * @param {string} title
70
+ */
71
+ function printSectionHeader(title) {
72
+ console.log(`\x1b[1m\x1b[97m${title}\x1b[0m`);
73
+ console.log(`\x1b[2m${'─'.repeat(title.length)}\x1b[0m`);
74
+ console.log('');
75
+ }
76
+
77
+ /**
78
+ * Print a focused section: header, then items or an empty-state message.
79
+ *
80
+ * @param {string} title - Section heading
81
+ * @param {string[]} items - Pre-formatted lines to print
82
+ * @param {string} emptyMsg - Canonical empty-state message (ends with '.')
83
+ */
84
+ function section(title, items, emptyMsg) {
85
+ printSectionHeader(title);
86
+
87
+ if (!items || items.length === 0) {
88
+ console.log(`\x1b[2m${emptyMsg}\x1b[0m`);
89
+ } else {
90
+ for (const item of items) {
91
+ console.log(item);
92
+ }
93
+ }
94
+ }
95
+
37
96
  /**
38
97
  * Renders the scan result based on the active focused mode.
39
98
  *
@@ -42,30 +101,46 @@ export function getFocusedModeInfo(args) {
42
101
  */
43
102
  export function renderFocusedMode(mode, result) {
44
103
  switch (mode) {
45
- case '--project-type':
46
- console.log(`Project Type: ${result.projectType}`);
104
+ case '--project-type': {
105
+ // projectType is always a string; 'Unknown' when undetected.
106
+ section('Project Type', [result.projectType], 'Unknown');
47
107
  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
- }
108
+ }
109
+
110
+ case '--frameworks': {
111
+ const frameworks = (!result.projectType || result.projectType === 'Unknown')
112
+ ? []
113
+ : [result.projectType];
114
+ section('Frameworks', frameworks, EMPTY.frameworks);
56
115
  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
- }
116
+ }
117
+
118
+ case '--entry-points': {
119
+ section('Entry Points', result.entryPoints || [], EMPTY.entryPoints);
65
120
  break;
66
-
67
- case '--structure':
121
+ }
122
+
123
+ case '--structure': {
68
124
  renderStructure(result);
69
125
  break;
126
+ }
127
+
128
+ case '--configs': {
129
+ section('Configuration Files', result.configs || [], EMPTY.configs);
130
+ break;
131
+ }
132
+
133
+ case '--scripts': {
134
+ const scriptsList = [];
135
+ if (result.scripts && result.scripts.length > 0) {
136
+ const maxNameLen = Math.max(...result.scripts.map(s => s.name.length));
137
+ for (const s of result.scripts) {
138
+ const paddedName = s.name.padEnd(maxNameLen, ' ');
139
+ scriptsList.push(`\x1b[97m${paddedName}\x1b[0m \x1b[2m${s.command}\x1b[0m`);
140
+ }
141
+ }
142
+ section('Package Scripts', scriptsList, EMPTY.scripts);
143
+ break;
144
+ }
70
145
  }
71
146
  }