clear_node_modules 1.4.3 → 1.5.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 (2) hide show
  1. package/package.json +3 -3
  2. package/src/lib.js +34 -65
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clear_node_modules",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "description": "Recursively remove node_modules folders from current directory and subdirectories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "homepage": "https://github.com/mooniitt/clear_node_modules#readme",
33
33
  "dependencies": {
34
- "ora": "^3.0.0",
35
- "rimraf": "^2.6.2"
34
+ "ora": "^5.4.1",
35
+ "rimraf": "^5.0.0"
36
36
  }
37
37
  }
package/src/lib.js CHANGED
@@ -1,10 +1,7 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
- const rimraf = require("rimraf");
3
+ const { rimraf } = require("rimraf");
4
4
  const ora = require("ora");
5
- const { promisify } = require("util");
6
-
7
- const rimrafAsync = promisify(rimraf);
8
5
 
9
6
  // 格式化文件大小
10
7
  function formatSize(bytes) {
@@ -40,11 +37,9 @@ function getDirSize(dir) {
40
37
 
41
38
  function wrap(LIMIT_SIZE, NODE_MODULES) {
42
39
  return async function clearDir(dirPath) {
43
- const tasks = [];
44
- let totalCount = 0;
45
- let doneCount = 0;
40
+ const foldersToDelete = [];
46
41
  let totalFreed = 0;
47
- let failedCount = 0;
42
+ let skippedCount = 0;
48
43
 
49
44
  // 扫描阶段
50
45
  const scanSpinner = ora("🔍 Scanning for node_modules...").start();
@@ -61,7 +56,8 @@ function wrap(LIMIT_SIZE, NODE_MODULES) {
61
56
  try {
62
57
  if (entry.isSymbolicLink()) continue;
63
58
  if (entry.name === NODE_MODULES && entry.isDirectory()) {
64
- totalCount++;
59
+ const size = getDirSize(subPath);
60
+ foldersToDelete.push({ path: subPath, size });
65
61
  } else if (entry.isDirectory()) {
66
62
  scan(subPath);
67
63
  }
@@ -76,77 +72,50 @@ function wrap(LIMIT_SIZE, NODE_MODULES) {
76
72
 
77
73
  scan(dirPath);
78
74
 
79
- if (totalCount === 0) {
75
+ if (foldersToDelete.length === 0) {
80
76
  scanSpinner.info("No node_modules found.");
81
77
  return;
82
78
  }
83
79
 
84
- scanSpinner.succeed(`Found ${totalCount} node_modules folder(s)`);
80
+ scanSpinner.succeed(`Found ${foldersToDelete.length} node_modules folder(s)`);
85
81
  console.log("");
86
82
 
87
- async function recurse(currentPath) {
88
- try {
89
- if (!fs.existsSync(currentPath)) return;
90
- const stat = fs.lstatSync(currentPath);
91
- if (!stat.isDirectory() || stat.isSymbolicLink()) return;
92
-
93
- const entries = fs.readdirSync(currentPath, { withFileTypes: true });
94
- if (entries.length === 0) return;
95
-
96
- for (const entry of entries) {
97
- const subPath = path.join(currentPath, entry.name);
98
- try {
99
- if (entry.isSymbolicLink()) continue;
100
-
101
- if (entry.name === NODE_MODULES && entry.isDirectory()) {
102
- const dirSize = getDirSize(subPath);
103
- const sizeMB = dirSize / 1024 / 1024;
104
-
105
- if (sizeMB < LIMIT_SIZE) {
106
- doneCount++;
107
- console.log(` ⏭️ [${doneCount}/${totalCount}] Skipped (${formatSize(dirSize)}) ${subPath}`);
108
- continue;
109
- }
83
+ // 串行删除,避免进度混乱
84
+ const total = foldersToDelete.length;
85
+ for (let i = 0; i < foldersToDelete.length; i++) {
86
+ const { path: folderPath, size } = foldersToDelete[i];
87
+ const sizeMB = size / 1024 / 1024;
88
+ const progress = `[${i + 1}/${total}]`;
89
+
90
+ if (sizeMB < LIMIT_SIZE) {
91
+ skippedCount++;
92
+ console.log(` ⏭️ ${progress} Skipped (${formatSize(size)}) ${folderPath}`);
93
+ continue;
94
+ }
110
95
 
111
- const spinner = ora({
112
- text: `[${++doneCount}/${totalCount}] Removing ${formatSize(dirSize)} - ${subPath}`,
113
- prefixText: " "
114
- }).start();
115
-
116
- const task = rimrafAsync(subPath)
117
- .then(() => {
118
- totalFreed += dirSize;
119
- spinner.succeed(`[${doneCount}/${totalCount}] Freed ${formatSize(dirSize)} - ${subPath}`);
120
- })
121
- .catch((err) => {
122
- failedCount++;
123
- spinner.fail(`[${doneCount}/${totalCount}] ✗ Failed - ${subPath}: ${err.message}`);
124
- });
125
- tasks.push(task);
126
- } else if (entry.isDirectory()) {
127
- await recurse(subPath);
128
- }
129
- } catch (e) {
130
- continue;
131
- }
132
- }
133
- } catch (e) {
134
- // 忽略
96
+ const spinner = ora({
97
+ text: `${progress} Removing ${formatSize(size)} - ${folderPath}`,
98
+ prefixText: " "
99
+ }).start();
100
+
101
+ try {
102
+ await rimraf(folderPath);
103
+ totalFreed += size;
104
+ spinner.succeed(`${progress} Freed ${formatSize(size)} - ${folderPath}`);
105
+ } catch (err) {
106
+ spinner.fail(`${progress} Failed - ${folderPath}: ${err.message}`);
135
107
  }
136
108
  }
137
-
138
- await recurse(dirPath);
139
- await Promise.all(tasks);
140
109
 
141
110
  // 汇总信息
142
111
  console.log("");
143
112
  console.log("─".repeat(50));
144
113
  console.log(` ✨ Completed!`);
145
- console.log(` 📁 Processed: ${totalCount} folder(s)`);
146
- console.log(` 💾 Freed: ${formatSize(totalFreed)}`);
147
- if (failedCount > 0) {
148
- console.log(` ⚠️ Failed: ${failedCount}`);
114
+ console.log(` 📁 Total: ${total} folder(s)`);
115
+ if (skippedCount > 0) {
116
+ console.log(` ⏭️ Skipped: ${skippedCount}`);
149
117
  }
118
+ console.log(` 💾 Freed: ${formatSize(totalFreed)}`);
150
119
  console.log("─".repeat(50));
151
120
  };
152
121
  }