|
|
@@ -58,18 +58,74 @@ if (packageJson.devDependencies) {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
-// 检查缺失的依赖
|
|
|
+// 快速获取已安装的包列表(直接从 node_modules 文件夹读取)
|
|
|
+function getInstalledPackagesFromFilesystem() {
|
|
|
+ const installedPackages = new Set();
|
|
|
+
|
|
|
+ if (!fs.existsSync(nodeModulesPath)) {
|
|
|
+ return installedPackages;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const entries = fs.readdirSync(nodeModulesPath, { withFileTypes: true });
|
|
|
+
|
|
|
+ for (const entry of entries) {
|
|
|
+ if (entry.isDirectory()) {
|
|
|
+ const packageName = entry.name;
|
|
|
+
|
|
|
+ // 跳过特殊目录
|
|
|
+ if (packageName.startsWith('.') || packageName === 'node_modules') {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否是有效的包(有 package.json)
|
|
|
+ const packageJsonPath = path.join(nodeModulesPath, packageName, 'package.json');
|
|
|
+ if (fs.existsSync(packageJsonPath)) {
|
|
|
+ installedPackages.add(packageName.toLowerCase());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理 scoped 包(如 @babel/core)
|
|
|
+ if (packageName.startsWith('@')) {
|
|
|
+ try {
|
|
|
+ const scopedPath = path.join(nodeModulesPath, packageName);
|
|
|
+ const scopedEntries = fs.readdirSync(scopedPath, { withFileTypes: true });
|
|
|
+ for (const scopedEntry of scopedEntries) {
|
|
|
+ if (scopedEntry.isDirectory()) {
|
|
|
+ const scopedPackageName = `${packageName}/${scopedEntry.name}`;
|
|
|
+ const scopedPackageJsonPath = path.join(scopedPath, scopedEntry.name, 'package.json');
|
|
|
+ if (fs.existsSync(scopedPackageJsonPath)) {
|
|
|
+ installedPackages.add(scopedPackageName.toLowerCase());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 忽略错误
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 忽略错误
|
|
|
+ }
|
|
|
+
|
|
|
+ return installedPackages;
|
|
|
+}
|
|
|
+
|
|
|
+// 快速检查缺失的依赖(使用文件系统)
|
|
|
const missingDependencies = [];
|
|
|
let installedCount = 0;
|
|
|
let missingCount = 0;
|
|
|
|
|
|
+// 一次性获取所有已安装的包(只检查一次文件系统)
|
|
|
+const installedPackagesSet = getInstalledPackagesFromFilesystem();
|
|
|
+
|
|
|
const depNames = Object.keys(allDependencies).sort();
|
|
|
|
|
|
for (const depName of depNames) {
|
|
|
- const packagePath = path.join(nodeModulesPath, depName);
|
|
|
- const packageJsonPath = path.join(packagePath, 'package.json');
|
|
|
+ const depNameLower = depName.toLowerCase();
|
|
|
|
|
|
- if (fs.existsSync(packageJsonPath)) {
|
|
|
+ // 快速检查(使用已获取的集合)
|
|
|
+ if (installedPackagesSet.has(depNameLower)) {
|
|
|
installedCount++;
|
|
|
} else {
|
|
|
missingDependencies.push(depName);
|
|
|
@@ -105,100 +161,79 @@ if (missingCount > 0) {
|
|
|
log(`[OK] All dependencies are installed (${Object.keys(allDependencies).length} packages)`, 'green');
|
|
|
}
|
|
|
|
|
|
-// 同步所有已安装的依赖到 dependencies.txt
|
|
|
-log('\nSyncing all installed dependencies to configs/dependencies.txt...', 'cyan');
|
|
|
-
|
|
|
-const syncResult = [];
|
|
|
-
|
|
|
-if (fs.existsSync(nodeModulesPath)) {
|
|
|
- // 遍历 node_modules 目录,查找所有 package.json 文件
|
|
|
- function findPackageJsonFiles(dir) {
|
|
|
- const files = [];
|
|
|
- try {
|
|
|
- const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
|
-
|
|
|
- for (const entry of entries) {
|
|
|
- const fullPath = path.join(dir, entry.name);
|
|
|
-
|
|
|
- if (entry.isDirectory()) {
|
|
|
- // 跳过 .bin 目录和其他特殊目录
|
|
|
- if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
|
- continue;
|
|
|
- }
|
|
|
- // 递归查找
|
|
|
- files.push(...findPackageJsonFiles(fullPath));
|
|
|
- } else if (entry.name === 'package.json') {
|
|
|
- files.push(fullPath);
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- // 忽略权限错误等
|
|
|
- }
|
|
|
- return files;
|
|
|
- }
|
|
|
-
|
|
|
- const packageJsonFiles = findPackageJsonFiles(nodeModulesPath);
|
|
|
+// 快速同步所有已安装的依赖到 dependencies.txt(只读取根级包,静默执行)
|
|
|
+function syncInstalledPackagesToFile() {
|
|
|
+ const syncResult = [];
|
|
|
|
|
|
- for (const file of packageJsonFiles) {
|
|
|
- try {
|
|
|
- const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
|
- if (pkg.name && pkg.version) {
|
|
|
- syncResult.push(`${pkg.name}==${pkg.version}`);
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- // 忽略解析错误
|
|
|
- }
|
|
|
+ if (!fs.existsSync(nodeModulesPath)) {
|
|
|
+ return syncResult;
|
|
|
}
|
|
|
|
|
|
- // 如果遍历结果为空,使用 npm list 作为后备方案
|
|
|
- if (syncResult.length === 0) {
|
|
|
- try {
|
|
|
- const npmListOutput = execSync('npm list --depth=0 --json', {
|
|
|
- encoding: 'utf-8',
|
|
|
- cwd: projectRoot,
|
|
|
- stdio: ['ignore', 'pipe', 'ignore']
|
|
|
- });
|
|
|
- const npmList = JSON.parse(npmListOutput);
|
|
|
- if (npmList.dependencies) {
|
|
|
- Object.keys(npmList.dependencies).forEach(depName => {
|
|
|
- const dep = npmList.dependencies[depName];
|
|
|
- if (dep && dep.version) {
|
|
|
- syncResult.push(`${depName}==${dep.version}`);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- // 忽略错误
|
|
|
- }
|
|
|
- }
|
|
|
-} else {
|
|
|
- // 如果 node_modules 不存在,使用 npm list
|
|
|
try {
|
|
|
- const npmListOutput = execSync('npm list --depth=0 --json', {
|
|
|
- encoding: 'utf-8',
|
|
|
- cwd: projectRoot,
|
|
|
- stdio: ['ignore', 'pipe', 'ignore']
|
|
|
- });
|
|
|
- const npmList = JSON.parse(npmListOutput);
|
|
|
- if (npmList.dependencies) {
|
|
|
- Object.keys(npmList.dependencies).forEach(depName => {
|
|
|
- const dep = npmList.dependencies[depName];
|
|
|
- if (dep && dep.version) {
|
|
|
- syncResult.push(`${depName}==${dep.version}`);
|
|
|
+ const entries = fs.readdirSync(nodeModulesPath, { withFileTypes: true });
|
|
|
+
|
|
|
+ for (const entry of entries) {
|
|
|
+ if (entry.isDirectory()) {
|
|
|
+ const packageName = entry.name;
|
|
|
+
|
|
|
+ // 跳过特殊目录
|
|
|
+ if (packageName.startsWith('.') || packageName === 'node_modules') {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理普通包
|
|
|
+ const packageJsonPath = path.join(nodeModulesPath, packageName, 'package.json');
|
|
|
+ if (fs.existsSync(packageJsonPath)) {
|
|
|
+ try {
|
|
|
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
|
+ if (pkg.name && pkg.version) {
|
|
|
+ syncResult.push(`${pkg.name}==${pkg.version}`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 忽略解析错误
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理 scoped 包(如 @babel/core)
|
|
|
+ if (packageName.startsWith('@')) {
|
|
|
+ try {
|
|
|
+ const scopedPath = path.join(nodeModulesPath, packageName);
|
|
|
+ const scopedEntries = fs.readdirSync(scopedPath, { withFileTypes: true });
|
|
|
+ for (const scopedEntry of scopedEntries) {
|
|
|
+ if (scopedEntry.isDirectory()) {
|
|
|
+ const scopedPackageJsonPath = path.join(scopedPath, scopedEntry.name, 'package.json');
|
|
|
+ if (fs.existsSync(scopedPackageJsonPath)) {
|
|
|
+ try {
|
|
|
+ const pkg = JSON.parse(fs.readFileSync(scopedPackageJsonPath, 'utf-8'));
|
|
|
+ if (pkg.name && pkg.version) {
|
|
|
+ syncResult.push(`${pkg.name}==${pkg.version}`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 忽略解析错误
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ // 忽略错误
|
|
|
+ }
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
}
|
|
|
} catch (error) {
|
|
|
// 忽略错误
|
|
|
}
|
|
|
+
|
|
|
+ return syncResult;
|
|
|
}
|
|
|
|
|
|
+// 同步所有已安装的依赖到 dependencies.txt(快速方法,静默执行)
|
|
|
+const syncResult = syncInstalledPackagesToFile();
|
|
|
+
|
|
|
// 去重并排序
|
|
|
const uniqueResult = [...new Set(syncResult)].sort();
|
|
|
|
|
|
// 写入文件(UTF-8 编码)
|
|
|
fs.writeFileSync(dependenciesFile, uniqueResult.join('\n') + '\n', 'utf-8');
|
|
|
|
|
|
-log(`[OK] Dependencies synced to ${dependenciesFile} (${uniqueResult.length} packages)`, 'green');
|
|
|
-
|
|
|
process.exit(0);
|