* 解密项目中的所有 JSC 文件 * @param {string} sourcePath 源项目路径 * @param {string} outputDir 输出目录 * @param {string} key 解密密钥 * @returns {Promise<{decrypted: number, failed: number}>}
(sourcePath, outputDir, key)
| 156 | |
| 157 | if (jscFiles.length === 0) { |
| 158 | logger.info('未发现 .jsc 文件,跳过解密步骤'); |
| 159 | return { decrypted: 0, failed: 0 }; |
| 160 | } |
| 161 | |
| 162 | logger.info(`发现 ${jscFiles.length} 个 .jsc 文件,开始解密...`); |
| 163 | |
| 164 | let decrypted = 0; |
| 165 | let failed = 0; |
| 166 | const concurrency = getMaxParallel(); |
| 167 | |
| 168 | await forEachPool(jscFiles, concurrency, async (jscFile) => { |
| 169 | const relativePath = path.relative(sourcePath, jscFile); |
| 170 | const outputFile = path.join(outputDir, relativePath.replace(/\.jsc$/, '.js')); |
| 171 | |
| 172 | await fsp.mkdir(path.dirname(outputFile), { recursive: true }); |
| 173 | |
| 174 | const data = await fsp.readFile(jscFile); |
| 175 | const result = decryptJscBuffer(data, key); |
| 176 | |
| 177 | if (result) { |
| 178 | await fsp.writeFile(outputFile, result); |
| 179 | decrypted += 1; |
| 180 | } else { |
| 181 | logger.warn(`解密失败: ${relativePath}`); |
| 182 | failed += 1; |
| 183 | } |
| 184 | }); |
| 185 | |
| 186 | logger.success(`解密完成: ${decrypted} 成功, ${failed} 失败`); |
| 187 | return { decrypted, failed }; |
| 188 | } |
| 189 | |
| 190 | module.exports = { scanJscFiles, extractKeyFromProject, decryptJscBuffer, decryptProject }; |
no test coverage detected