tri-cli 0.0.53 → 0.0.54

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 (2) hide show
  1. package/dist/cli.js +28 -77
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -73,33 +73,19 @@ const getDirSizeAsync = async dirPath => {
73
73
  }
74
74
  };
75
75
 
76
- // Fast file counting - much faster than size calculation
76
+ // Fast file counting using shell command
77
77
  const countFilesAsync = async dirPath => {
78
78
  try {
79
79
  const stats = fs.statSync(dirPath);
80
80
  if (!stats.isDirectory()) return 1;
81
- let count = 0;
82
- const countRecursive = async dir => {
83
- try {
84
- const entries = fs.readdirSync(dir, {
85
- withFileTypes: true
86
- });
87
- for (const entry of entries) {
88
- // Skip hidden files
89
- if (entry.name.startsWith('.')) continue;
90
- const fullPath = path.join(dir, entry.name);
91
- if (entry.isFile()) {
92
- count++;
93
- } else if (entry.isDirectory()) {
94
- await countRecursive(fullPath);
95
- }
96
- }
97
- } catch {
98
- // Skip directories we can't read
99
- }
100
- };
101
- await countRecursive(dirPath);
102
- return count;
81
+
82
+ // Use find command for fast counting, excluding hidden files
83
+ const escapedPath = dirPath.replace(/"/g, '\\"');
84
+ const {
85
+ stdout
86
+ } = await execAsync(`find "${escapedPath}" -type f ! -path '*/.*' 2>/dev/null | wc -l`);
87
+ const count = parseInt(stdout.trim(), 10);
88
+ return isNaN(count) ? 0 : count;
103
89
  } catch {
104
90
  return 0;
105
91
  }
@@ -451,64 +437,29 @@ const TreeVisualization = ({
451
437
  collectNodes(node);
452
438
  if (nodesToCount.length === 0) return; // Nothing to count
453
439
 
440
+ // Sort nodes by depth (shallowest first) for top-down display
441
+ nodesToCount.sort((a, b) => a.depth - b.depth);
442
+
454
443
  // Mark all nodes as loading
455
- const pathsToLoad = nodesToCount.map(n => n.data.path);
456
- setLoadingPaths(prev => new Set([...prev, ...pathsToLoad]));
444
+ const loadingSet = new Set(nodesToCount.map(n => n.data.path));
445
+ setLoadingPaths(loadingSet);
457
446
  const newMap = new Map(calculatedCounts);
458
447
 
459
- // Count and stream updates for each node individually
460
- for (const targetNode of nodesToCount) {
461
- // For directories, stream partial counts as we count
462
- if (!targetNode.data.isFile) {
463
- let runningCount = 0;
464
- let updateCounter = 0;
465
- const countRecursive = async dir => {
466
- try {
467
- const entries = fs.readdirSync(dir, {
468
- withFileTypes: true
469
- });
470
- for (const entry of entries) {
471
- // Skip hidden files
472
- if (entry.name.startsWith('.')) continue;
473
- const fullPath = path.join(dir, entry.name);
474
- if (entry.isFile()) {
475
- runningCount++;
476
- updateCounter++;
477
- // Stream update every 100 files for better performance
478
- if (updateCounter >= 100) {
479
- updateCounter = 0;
480
- newMap.set(targetNode.data.path, runningCount);
481
- React.startTransition(() => {
482
- setCalculatedCounts(new Map(newMap));
483
- });
484
- await new Promise(r => setTimeout(r, 0));
485
- }
486
- } else if (entry.isDirectory()) {
487
- await countRecursive(fullPath);
488
- }
489
- }
490
- } catch {
491
- // Skip directories we can't read
492
- }
493
- };
494
- await countRecursive(targetNode.data.path);
495
- newMap.set(targetNode.data.path, runningCount);
496
- } else {
497
- // Files are always 1
498
- newMap.set(targetNode.data.path, 1);
499
- }
448
+ // Process all nodes in parallel, but update UI as each completes
449
+ const promises = nodesToCount.map(async targetNode => {
450
+ const count = await countFilesAsync(targetNode.data.path);
500
451
 
501
- // Stream the final update and remove from loading
502
- React.startTransition(() => {
503
- setCalculatedCounts(new Map(newMap));
504
- setLoadingPaths(prev => {
505
- const next = new Set(prev);
506
- next.delete(targetNode.data.path);
507
- return next;
508
- });
509
- });
510
- await new Promise(r => setTimeout(r, 0));
511
- }
452
+ // Update immediately when this specific node completes
453
+ newMap.set(targetNode.data.path, count);
454
+ loadingSet.delete(targetNode.data.path);
455
+
456
+ // Trigger UI update
457
+ setCalculatedCounts(new Map(newMap));
458
+ setLoadingPaths(new Set(loadingSet));
459
+ });
460
+
461
+ // Wait for all counts to complete
462
+ await Promise.all(promises);
512
463
  };
513
464
  const getLastModifiedAsync = async node => {
514
465
  // Collect node and all its descendants
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tri-cli",
3
- "version": "0.0.53",
3
+ "version": "0.0.54",
4
4
  "description": "Interactive CLI directory tree visualizer with treemap view",
5
5
  "author": "Jared Wilber",
6
6
  "license": "MIT",