patch-asar
Version:
Patch .asar archives
76 lines (74 loc) • 2.79 kB
JavaScript
import isDirectory from "./functions/isDirectory.js";
import isFile from "./functions/isFile.js";
import { promisify } from "util";
import mkdirp from "./functions/mkdirp.js";
import asar from "@electron/asar";
import { cp } from "fs/promises";
import { basename, extname, join } from "path";
import executePatches from "./executePatches.js";
import rimraf from "./functions/rimraf.js";
export default async function patchAsar(
asarFilePath,
patchFolderPath,
options = {}
) {
if (typeof options != "object")
throw new Error("Options must be an object or null.");
let {
workingDirectory = null,
keepWorkingDirectory = false,
beforeFinishPatching = null,
} = options || {};
let outputPath = options.outputPath || options.outputFile || null;
if (
beforeFinishPatching !== null &&
typeof beforeFinishPatching != "function"
)
throw new Error(
"beforeFinishPatching must be a function (that returns true or a promise) or null"
);
if (typeof keepWorkingDirectory != "boolean")
throw new Error("keepWorkingDirectory must be a boolean");
if (
typeof asarFilePath != "string" ||
!asarFilePath.endsWith(".asar") ||
!(await isFile(asarFilePath))
)
throw new Error("Invalid Asar File Path");
if (
typeof patchFolderPath != "string" ||
!(await isDirectory(patchFolderPath))
)
throw new Error("Invalid Patch Folder Path");
if (
outputPath !== null &&
(typeof outputPath != "string" || (await isDirectory(outputPath)))
)
throw new Error("Invalid Output File Path");
if (workingDirectory !== null && typeof workingDirectory != "string")
throw new Error("Invalid Working Directory Path");
if (outputPath === null) outputPath = asarFilePath; // Patch in place
if (workingDirectory === null)
workingDirectory = join(import.meta.dirname, "./build/");
workingDirectory = join(
workingDirectory,
basename(asarFilePath, extname(asarFilePath))
);
await rimraf(workingDirectory);
await mkdirp(workingDirectory);
await asar.extractAll(asarFilePath, workingDirectory);
await cp(patchFolderPath, workingDirectory, { recursive: true, force: true });
await executePatches(workingDirectory, patchFolderPath);
// Allow the user to edit the working directory before completing our patch using an async function
if (beforeFinishPatching) {
const prom = beforeFinishPatching(workingDirectory);
if (!(prom instanceof Promise) && promise !== true) {
throw new Error(
"Expected a promise from the beforeFinishPatching function or true to designate a finished sync function"
);
}
}
await rimraf(outputPath);
await asar.createPackage(workingDirectory, outputPath);
if (keepWorkingDirectory === false) await rimraf(workingDirectory);
}