codeinf 1.0.8 → 1.1.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/bin/cli.js +38 -1
- package/index.js +63 -4
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -173,6 +173,31 @@ function progressBar(value, max, width = 20) {
|
|
|
173
173
|
return `[${bar}]`;
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
// Loading progress bar for scanning
|
|
177
|
+
function renderLoadingBar(current, total, currentFile, isDiscovery = false, width = 30) {
|
|
178
|
+
// Get filename only
|
|
179
|
+
const fileName = path.basename(currentFile || '');
|
|
180
|
+
const truncatedFile = fileName.length > 25 ? fileName.substring(0, 22) + '...' : fileName;
|
|
181
|
+
|
|
182
|
+
// Clear line and render
|
|
183
|
+
process.stdout.write('\r\x1b[K'); // Clear line
|
|
184
|
+
|
|
185
|
+
if (isDiscovery) {
|
|
186
|
+
// Discovery mode - show spinner and count
|
|
187
|
+
const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][Math.floor(Date.now() / 80) % 10];
|
|
188
|
+
process.stdout.write(` ${c(spinner, 'cyan')} ${c('Scanning:', 'yellow')} Found ${c(total.toString(), 'cyan')} files ${c(truncatedFile, 'dim')}`);
|
|
189
|
+
} else {
|
|
190
|
+
// Analysis mode - show progress bar
|
|
191
|
+
const percentage = total > 0 ? Math.round((current / total) * 100) : 0;
|
|
192
|
+
const filled = Math.round((current / total) * width);
|
|
193
|
+
const empty = width - filled;
|
|
194
|
+
const bar = c('█'.repeat(filled), 'green') + c('░'.repeat(empty), 'gray');
|
|
195
|
+
process.stdout.write(` ${c('Analyzing:', 'yellow')} [${bar}] ${c(percentage + '%', 'cyan')} ${c(current + '/' + total, 'gray')} ${c(truncatedFile, 'dim')}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
176
201
|
// Format output as table with colors
|
|
177
202
|
function formatTable(data, useColor = true) {
|
|
178
203
|
const { summary, byExtension, largestFiles, path: targetPath } = data;
|
|
@@ -271,12 +296,24 @@ async function main() {
|
|
|
271
296
|
}
|
|
272
297
|
|
|
273
298
|
try {
|
|
299
|
+
// Show loading bar for non-JSON output
|
|
300
|
+
const useLoadingBar = options.format !== 'json' && !options.noColor;
|
|
301
|
+
|
|
274
302
|
const result = analyze(options.path, {
|
|
275
303
|
extensions: options.extensions,
|
|
276
304
|
ignoreDirs: options.ignoreDirs,
|
|
277
305
|
ignoreFiles: options.ignoreFiles,
|
|
278
306
|
includeNodeModules: options.includeNodeModules
|
|
279
|
-
})
|
|
307
|
+
}, useLoadingBar ? (current, total, currentFile, isDiscovery) => {
|
|
308
|
+
renderLoadingBar(current, total, currentFile, isDiscovery);
|
|
309
|
+
} : null);
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
// Clear loading bar line if it was shown
|
|
314
|
+
if (useLoadingBar) {
|
|
315
|
+
process.stdout.write('\r\x1b[K\n');
|
|
316
|
+
}
|
|
280
317
|
|
|
281
318
|
if (options.format === 'json') {
|
|
282
319
|
console.log(JSON.stringify(result, null, 2));
|
package/index.js
CHANGED
|
@@ -68,9 +68,10 @@ function getFileStats(filePath) {
|
|
|
68
68
|
* Recursively scan directory for files
|
|
69
69
|
* @param {string} dir - Directory to scan
|
|
70
70
|
* @param {Object} options - Options
|
|
71
|
+
* @param {Function} onProgress - Callback for progress updates (current, total, currentFile)
|
|
71
72
|
* @returns {Object[]}
|
|
72
73
|
*/
|
|
73
|
-
function scanDirectory(dir, options = {}) {
|
|
74
|
+
function scanDirectory(dir, options = {}, onProgress = null) {
|
|
74
75
|
const {
|
|
75
76
|
extensions = [],
|
|
76
77
|
ignoreDirs = [],
|
|
@@ -85,7 +86,55 @@ function scanDirectory(dir, options = {}) {
|
|
|
85
86
|
: [...ignoreDirs, 'node_modules'];
|
|
86
87
|
|
|
87
88
|
const results = [];
|
|
89
|
+
let totalFiles = 0;
|
|
90
|
+
let processedFiles = 0;
|
|
91
|
+
let lastProgressUpdate = 0;
|
|
92
|
+
const PROGRESS_INTERVAL = 50; // Update every 50ms
|
|
88
93
|
|
|
94
|
+
// First pass: count total files with progress
|
|
95
|
+
function countFiles(currentPath) {
|
|
96
|
+
const fileName = path.basename(currentPath);
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const stats = fs.statSync(currentPath);
|
|
100
|
+
const isDir = stats.isDirectory();
|
|
101
|
+
|
|
102
|
+
if (isDir) {
|
|
103
|
+
if (shouldIgnoreDir(currentPath, dirIgnores)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
} else {
|
|
107
|
+
if (ignoreFiles.includes(fileName)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (stats.isDirectory()) {
|
|
113
|
+
if (recursive) {
|
|
114
|
+
const items = fs.readdirSync(currentPath);
|
|
115
|
+
for (const item of items) {
|
|
116
|
+
countFiles(path.join(currentPath, item));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
const ext = path.extname(currentPath).toLowerCase();
|
|
121
|
+
if (extensions.length === 0 || extensions.includes(ext)) {
|
|
122
|
+
totalFiles++;
|
|
123
|
+
|
|
124
|
+
// Throttle progress updates during discovery
|
|
125
|
+
const now = Date.now();
|
|
126
|
+
if (onProgress && totalFiles % 500 === 0 && now - lastProgressUpdate >= 50) {
|
|
127
|
+
onProgress(0, totalFiles, currentPath, true); // true = discovery mode
|
|
128
|
+
lastProgressUpdate = now;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// Skip files we can't access
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Second pass: scan files with throttled progress
|
|
89
138
|
function scan(currentPath) {
|
|
90
139
|
const fileName = path.basename(currentPath);
|
|
91
140
|
|
|
@@ -118,6 +167,14 @@ function scanDirectory(dir, options = {}) {
|
|
|
118
167
|
const fileStats = getFileStats(currentPath);
|
|
119
168
|
if (fileStats) {
|
|
120
169
|
results.push(fileStats);
|
|
170
|
+
processedFiles++;
|
|
171
|
+
|
|
172
|
+
// Throttle progress updates - only update every 100 files or 100ms
|
|
173
|
+
const now = Date.now();
|
|
174
|
+
if (onProgress && (processedFiles % 100 === 0 || now - lastProgressUpdate >= 100)) {
|
|
175
|
+
onProgress(processedFiles, totalFiles, currentPath, false); // false = analysis mode
|
|
176
|
+
lastProgressUpdate = now;
|
|
177
|
+
}
|
|
121
178
|
}
|
|
122
179
|
}
|
|
123
180
|
}
|
|
@@ -126,6 +183,8 @@ function scanDirectory(dir, options = {}) {
|
|
|
126
183
|
}
|
|
127
184
|
}
|
|
128
185
|
|
|
186
|
+
// Count files first, then scan with progress
|
|
187
|
+
countFiles(dir);
|
|
129
188
|
scan(dir);
|
|
130
189
|
return results;
|
|
131
190
|
}
|
|
@@ -134,9 +193,10 @@ function scanDirectory(dir, options = {}) {
|
|
|
134
193
|
* Analyze code statistics
|
|
135
194
|
* @param {string} targetPath - Path to analyze
|
|
136
195
|
* @param {Object} options - Analysis options
|
|
196
|
+
* @param {Function} onProgress - Callback for progress updates
|
|
137
197
|
* @returns {Object}
|
|
138
198
|
*/
|
|
139
|
-
function analyze(targetPath = '.', options = {}) {
|
|
199
|
+
function analyze(targetPath = '.', options = {}, onProgress = null) {
|
|
140
200
|
const resolvedPath = path.resolve(targetPath);
|
|
141
201
|
|
|
142
202
|
if (!fs.existsSync(resolvedPath)) {
|
|
@@ -147,7 +207,7 @@ function analyze(targetPath = '.', options = {}) {
|
|
|
147
207
|
let files = [];
|
|
148
208
|
|
|
149
209
|
if (stats.isDirectory()) {
|
|
150
|
-
files = scanDirectory(resolvedPath, options);
|
|
210
|
+
files = scanDirectory(resolvedPath, options, onProgress);
|
|
151
211
|
} else {
|
|
152
212
|
const fileStats = getFileStats(resolvedPath);
|
|
153
213
|
if (fileStats) {
|
|
@@ -155,7 +215,6 @@ function analyze(targetPath = '.', options = {}) {
|
|
|
155
215
|
}
|
|
156
216
|
}
|
|
157
217
|
|
|
158
|
-
// Calculate totals
|
|
159
218
|
const totalStats = files.reduce((acc, file) => ({
|
|
160
219
|
files: acc.files + 1,
|
|
161
220
|
totalLines: acc.totalLines + file.totalLines,
|
package/package.json
CHANGED