@zozzona/js
Version:
Advanced source protection toolkit (obfuscate → minify → encrypt) with reversible unpacking and git-safe automation.
226 lines (178 loc) • 6.88 kB
JavaScript
import fs from "fs-extra";
import path from "path";
import { execSync } from "child_process";
import { fileURLToPath } from "url";
import crypto from "crypto";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const TEMPLATE_DIR = path.join(__dirname, "../templates");
function generateMapKey() {
return crypto.randomBytes(32).toString("base64");
}
export function loadPackConfig() {
const configPath = path.resolve("pack.config.json");
if (!fs.existsSync(configPath)) return { folders: [], files: [], ignore: [] };
return JSON.parse(fs.readFileSync(configPath, "utf-8"));
}
function ensureEnvFileWithMessaging() {
const envPath = path.resolve(".env");
if (!fs.existsSync(envPath)) {
const key = generateMapKey();
fs.writeFileSync(envPath, `# Auto-generated by Zozzona.js\nMAP_KEY=${key}\n`, "utf-8");
console.log(`✔ Created .env at: ${envPath}`);
} else {
const content = fs.readFileSync(envPath, "utf-8");
if (!content.includes("MAP_KEY=")) {
const key = generateMapKey();
fs.appendFileSync(envPath, `\nMAP_KEY=${key}\n`);
console.log(`✔ Added MAP_KEY to existing .env`);
} else {
console.log(`ℹ Using existing MAP_KEY from: ${envPath}`);
}
}
const final = fs.readFileSync(envPath, "utf-8");
console.log("\n━━━━━━━━━━━━━━━━━━━━");
console.log("📄 Your .env now contains:\n");
console.log(final.trim());
console.log("━━━━━━━━━━━━━━━━━━━━\n");
}
function ensurePackConfig() {
if (!fs.existsSync("pack.config.json")) {
fs.copyFileSync(path.join(TEMPLATE_DIR, "pack.config.json"), "pack.config.json");
console.log("✔ Created pack.config.json");
}
}
function ensurePackageScripts() {
const pkgPath = path.resolve("package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
pkg.scripts = pkg.scripts || {};
let changed = false;
const required = {
obfuscate: "node node_modules/@zozzona/js/src/obfuscate.js obfuscate",
deobfuscate: "node node_modules/@zozzona/js/src/obfuscate.js deobfuscate",
minify: "node node_modules/@zozzona/js/src/minify.js minify",
deminify: "node node_modules/@zozzona/js/src/minify.js restore",
pack: "zozzona pack",
unpack: "zozzona unpack",
"pack:dist": "zozzona pack:dist"
};
for (const [name, value] of Object.entries(required)) {
if (!pkg.scripts[name]) {
pkg.scripts[name] = value;
changed = true;
}
}
// Auto-add build hook if not present
if (!pkg.scripts.build) {
console.warn("⚠ No build script detected. Not modifying build.");
} else if (!pkg.scripts.build.includes("pack:dist")) {
pkg.scripts.build = pkg.scripts.build + " && npm run pack:dist";
changed = true;
console.log("✔ Updated build script to automatically pack dist");
}
if (changed) {
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
console.log("✔ Updated package.json with Zozzona scripts");
}
}
/*function installHusky() {
console.log("📦 Installing Husky...");
execSync("npm install husky --save-dev", { stdio: "inherit" });
console.log("🔧 Running husky install...");
execSync("npx husky install", { stdio: "inherit" });
fs.mkdirpSync(".husky");
const pre = path.join(".husky", "pre-commit");
const post = path.join(".husky", "post-commit");
fs.copyFileSync(path.join(TEMPLATE_DIR, "husky-pre-commit.sh"), pre);
fs.copyFileSync(path.join(TEMPLATE_DIR, "husky-post-commit.sh"), post);
fs.chmodSync(pre, 0o755);
fs.chmodSync(post, 0o755);
console.log("✔ Husky hooks installed");
}*/
// ─────────────────────────────────────────────
// Install Husky (v9+) with modern hook templates
// ─────────────────────────────────────────────
function installHusky() {
console.log("📦 Installing Husky...");
// Install husky quietly
execSync("npm install husky --save-dev", { stdio: "inherit" });
console.log("🔧 Initializing Husky...");
execSync("npx husky install", { stdio: "inherit" });
// Ensure .husky folder exists
fs.mkdirpSync(".husky");
// -----------------------------------------------------
// 1. Create .huskyrc — REQUIRED FOR SHELL MODE IN V9
// -----------------------------------------------------
const huskyrcPath = ".huskyrc";
const huskyrcContent = {
shell: true
};
fs.writeFileSync(huskyrcPath, JSON.stringify(huskyrcContent, null, 2));
console.log("✔ Added .huskyrc (shell=true)");
// -----------------------------------------------------
// 2. Pre-commit hook
// -----------------------------------------------------
const preCommit = `#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
# Change to project root
cd "$(git rev-parse --show-toplevel)"
NODE_PATH="$(which node 2>/dev/null | xargs dirname)"
export PATH="$NODE_PATH:/usr/local/bin:/opt/homebrew/bin:$PATH"
echo "🔒 Packing before commit..."
npm run pack || exit 1
echo "📝 Staging protected files..."
git add -A :/ || exit 1
`;
fs.writeFileSync(".husky/pre-commit", preCommit);
fs.chmodSync(".husky/pre-commit", 0o755);
console.log("✔ Added pre-commit hook");
// -----------------------------------------------------
// 3. Post-commit hook
// -----------------------------------------------------
const postCommit = `#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
cd "$(git rev-parse --show-toplevel)"
NODE_PATH="$(which node 2>/dev/null | xargs dirname)"
export PATH="$NODE_PATH:/usr/local/bin:/opt/homebrew/bin:$PATH"
echo "🔓 Unpacking after commit..."
npm run unpack || exit 0
`;
fs.writeFileSync(".husky/post-commit", postCommit);
fs.chmodSync(".husky/post-commit", 0o755);
console.log("✔ Added post-commit hook");
console.log("✔ Husky installed successfully");
}
export function runCLI() {
const cmd = process.argv[2];
if (!cmd || ["help", "-h", "--help"].includes(cmd)) {
console.log(`
Zozzona.js CLI
--------------
zozzona init
zozzona pack
zozzona unpack
zozzona pack:dist
zozzona version
`);
return;
}
if (cmd === "version") {
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
console.log(pkg.version);
return;
}
if (cmd === "init") {
ensureEnvFileWithMessaging();
ensurePackConfig();
ensurePackageScripts();
installHusky();
return;
}
if (cmd === "pack" || cmd === "unpack" || cmd === "pack:dist") {
const runner = path.join(__dirname, "runner.js");
execSync(`node "${runner}" ${cmd}`, { stdio: "inherit" });
return;
}
console.error("Unknown command:", cmd);
process.exit(1);
}