#!/usr/bin/env node /** * 根据 x64 和 arm64 架构分别生成 dependencies.txt * 功能:从 node_modules 读取已安装包,按架构替换平台相关包,分别写入 x64 和 arm64 目录 */ const fs = require('fs'); const path = require('path'); const scriptDir = __dirname; const projectRoot = path.resolve(scriptDir, '..', '..'); const config = require(path.join(projectRoot, 'configs', 'config.js')); const nodeDir = config.nodeDir || path.join(scriptDir, '..', 'node'); const nodeModulesPath = path.join(nodeDir, 'node_modules'); const x64Dir = path.join(scriptDir, 'x64'); const arm64Dir = path.join(scriptDir, 'arm64'); // 平台相关包的映射(x64 ↔ arm64 一一对应) const X64_TO_ARM64 = { '@esbuild/win32-x64': '@esbuild/win32-arm64', '@parcel/watcher-win32-x64': '@parcel/watcher-win32-arm64', '@rollup/rollup-win32-x64-gnu': '@rollup/rollup-win32-arm64-gnu', '@rollup/rollup-win32-x64-msvc': '@rollup/rollup-win32-arm64-msvc' }; const ARM64_TO_X64 = Object.fromEntries( Object.entries(X64_TO_ARM64).map(([k, v]) => [v, k]) ); const colors = { reset: '\x1b[0m', green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m' }; function log(message, color = 'reset') { console.log(`${colors[color]}${message}${colors.reset}`); } function collectPackagesFromNodeModules() { const packages = new Map(); if (!fs.existsSync(nodeModulesPath)) { return packages; } function scan(dir, prefix = '') { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory() && !entry.name.startsWith('.')) { const fullName = prefix ? `${prefix}/${entry.name}` : entry.name; const pkgPath = path.join(dir, entry.name, 'package.json'); if (fs.existsSync(pkgPath)) { try { const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); if (pkg.name && pkg.version) { packages.set(pkg.name.toLowerCase(), `${pkg.name}==${pkg.version}`); } } catch (_) {} } if (entry.name.startsWith('@')) { scan(path.join(dir, entry.name), entry.name); } } } } scan(nodeModulesPath); return packages; } function buildArchList(packagesMap, targetArch) { const toExclude = targetArch === 'x64' ? Object.values(X64_TO_ARM64) : Object.keys(X64_TO_ARM64); const swapMap = targetArch === 'x64' ? ARM64_TO_X64 : X64_TO_ARM64; const result = []; for (const [nameLower, nameVersion] of packagesMap) { if (toExclude.some(p => nameLower === p.toLowerCase())) { continue; } result.push(nameVersion); } // 若 node_modules 中有对方架构的平台包,为目标架构添加对应的同版本包 for (const [fromPkg, toPkg] of Object.entries(swapMap)) { const fromEntry = [...packagesMap.entries()].find(([k]) => k === fromPkg.toLowerCase()); if (fromEntry) { const ver = fromEntry[1].includes('==') ? fromEntry[1].split('==')[1] : 'latest'; const line = `${toPkg}==${ver}`; if (!result.some(r => r.startsWith(toPkg + '=='))) { result.push(line); } } } return [...new Set(result)].sort(); } function main() { log('Generating x64 and arm64 dependencies.txt...', 'cyan'); const packagesMap = collectPackagesFromNodeModules(); if (packagesMap.size === 0) { log('[WARN] nodejs/node/node_modules not found or empty. Run npm install first.', 'yellow'); process.exit(1); } const x64List = buildArchList(packagesMap, 'x64'); const arm64List = buildArchList(packagesMap, 'arm64'); if (!fs.existsSync(x64Dir)) fs.mkdirSync(x64Dir, { recursive: true }); if (!fs.existsSync(arm64Dir)) fs.mkdirSync(arm64Dir, { recursive: true }); const x64File = path.join(x64Dir, 'dependencies.txt'); const arm64File = path.join(arm64Dir, 'dependencies.txt'); fs.writeFileSync(x64File, x64List.join('\n') + '\n', 'utf-8'); fs.writeFileSync(arm64File, arm64List.join('\n') + '\n', 'utf-8'); log(`[OK] x64/dependencies.txt: ${x64List.length} packages`, 'green'); log(`[OK] arm64/dependencies.txt: ${arm64List.length} packages`, 'green'); } main();