UNPKG

@zozzona/js

Version:

Advanced source protection toolkit (obfuscate → minify → encrypt) with reversible unpacking and git-safe automation.

226 lines (178 loc) 6.88 kB
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); }