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.
Files changed (3) hide show
  1. package/bin/cli.js +38 -1
  2. package/index.js +63 -4
  3. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeinf",
3
- "version": "1.0.8",
3
+ "version": "1.1.0",
4
4
  "description": "A CLI tool to analyze code statistics like lines of code, file counts, and more with filtering capabilities",
5
5
  "main": "index.js",
6
6
  "bin": "./bin/cli.js",