esbuild-obfuscator-plugin
Version:
JavaScript obfuscator plugin for esbuild
79 lines (78 loc) • 2.6 kB
JavaScript
// index.ts
import { promises } from "node:fs";
import { transform } from "esbuild";
import JavaScriptObfuscator from "javascript-obfuscator";
import MicroMatch from "micromatch";
function ObfuscatorPlugin(options) {
const { obfuscateOutput = false, filter = [], ...obfuscateOptions } = options;
return {
name: "obfuscator",
setup: (build) => {
function shouldObfuscate(path) {
if (typeof filter === "function") {
return filter(path);
} else if (Array.isArray(filter) && filter.length > 0) {
return isMatch(path, filter);
}
return true;
}
if (obfuscateOutput) {
build.initialOptions.write = false;
return build.onEnd(async ({ outputFiles, errors }) => {
if (!errors.length && outputFiles?.length) {
for (const output of outputFiles) {
if (!shouldObfuscate(output.path)) return;
const obfuscatedCode = JavaScriptObfuscator.obfuscate(
output.text,
obfuscateOptions
).getObfuscatedCode();
await promises.writeFile(output.path, obfuscatedCode);
}
}
});
}
build.onLoad(
{
filter: /\.([cm]?[jt]sx?)$/i
},
async (args) => {
if (!shouldObfuscate(args.path)) return;
const extension = args.path.split(".").pop()?.match(/([jt]sx?)$/i);
if (!extension) {
throw new Error(`Could not determine loader for ${args.path}`);
}
const loader = extension[1]?.toLowerCase();
const toInject = [];
if (options.inject) {
for (const path of Object.keys(options.inject)) {
if (isMatch(args.path, path) && options.inject[path]) {
toInject.push(
typeof options.inject[path] === "string" ? options.inject[path] : options.inject[path].join("\n")
);
}
}
}
const result = await transform(await promises.readFile(args.path, "utf8"), {
loader,
banner: toInject.join("\n"),
sourcemap: false
});
const obfuscatedCode = JavaScriptObfuscator.obfuscate(
result.code,
options
).getObfuscatedCode();
return {
contents: obfuscatedCode,
loader
};
}
);
}
};
}
function isMatch(path, pattern) {
return MicroMatch.isMatch(path, pattern, { basename: true });
}
export {
ObfuscatorPlugin as default
};