import fs from "node:fs"; import path from "node:path"; import { spawnSync } from "node:child_process"; import TOML from "toml"; import { applyConfiguredTransforms, type PatchConfig } from "./extractors"; const root = import.meta.dir; const inputRoot = path.join(root, "inputs"); const outputRoot = path.join(root, "outputs"); const tempRoot = path.join(root, "temp"); const apktoolJar = path.join(root, "java", "apktool_2.4.1.jar"); function run(command: string, args: string[]): void { const result = spawnSync(command, args, { cwd: root, stdio: "inherit" }); if (result.error) throw result.error; if (result.status !== 0) throw new Error(`${command} exited with status ${result.status}`); } function processApp(file: string): void { const input = path.join(inputRoot, file); const appName = path.basename(file, path.extname(file)); const workDir = path.join(tempRoot, appName); const configPath = path.join(root, "apkpatch", `${appName}.toml`); const output = path.join(outputRoot, `${appName}_patched.apk`); console.log(`[+] Processing ${file}`); fs.rmSync(workDir, { recursive: true, force: true }); run("java", ["-jar", apktoolJar, "d", "-f", input, "-o", workDir]); if (!fs.existsSync(configPath)) throw new Error(`Missing patch configuration ${configPath}`); const config = TOML.parse(fs.readFileSync(configPath, "utf8")) as PatchConfig; applyConfiguredTransforms(workDir, config, root); fs.mkdirSync(outputRoot, { recursive: true }); run("java", ["-jar", apktoolJar, "b", workDir, "-o", output]); console.log(`[ok] Rebuilt ${output}`); } function main(): void { fs.mkdirSync(outputRoot, { recursive: true }); fs.mkdirSync(tempRoot, { recursive: true }); const requested = process.argv.slice(2); const files = requested.length ? requested.map((name) => (name.endsWith(".apk") ? name : `${name}.apk`)) : fs .readdirSync(inputRoot) .filter((name) => name.endsWith(".apk")) .sort(); let failures = 0; for (const file of files) { try { processApp(file); } catch (error) { failures++; console.error(`[failed] ${file}`, error); } } if (failures) process.exitCode = 1; } main();