const fs = require('fs'); const path = require('path'); const JavaScriptObfuscator = require('javascript-obfuscator'); // Configuration const config = { compact: true, controlFlowFlattening: false, controlFlowFlatteningThreshold: 0.75, deadCodeInjection: false, deadCodeInjectionThreshold: 0.4, debugProtection: false, debugProtectionInterval: 0, disableConsoleOutput: false, // Keep console.log for debugging identifierNamesGenerator: 'hexadecimal', log: false, numbersToExpressions: false, renameGlobals: false, selfDefending: false, simplify: true, splitStrings: false, splitStringsChunkLength: 10, stringArray: true, stringArrayEncoding: [], stringArrayThreshold: 0.75, transformObjectKeys: false, unicodeEscapeSequence: false }; // Directories to process const directories = [ 'resources/js', 'resources/js/service' ]; // File extensions to minify const extensions = ['.js']; // Files to skip (already minified or external libraries) const skipFiles = [ 'app.js', // Already processed by Laravel Mix 'app.js.LICENSE.txt', '*.min.js', // Already minified 'sweetalert.min.js', // External minified library 'owl.carousel.js' // External library ]; function shouldSkipFile(filename) { return skipFiles.some(pattern => { if (pattern.includes('*')) { const regex = new RegExp(pattern.replace('*', '.*')); return regex.test(filename); } return filename === pattern; }); } async function minifyFile(filePath) { try { const source = fs.readFileSync(filePath, 'utf8'); const result = JavaScriptObfuscator.obfuscate(source, config); if (result.error) { console.error(`❌ Error obfuscating ${filePath}:`, result.error); return false; } // Create minified file path in public/js directory const relativePath = path.relative('resources/js', filePath); const dir = path.dirname(relativePath); const ext = path.extname(filePath); const basename = path.basename(filePath, ext); // Create output directory structure in public/js const outputPath = path.join('public/js', dir); if (!fs.existsSync(outputPath)) { fs.mkdirSync(outputPath, { recursive: true }); } const minifiedPath = path.join(outputPath, `${basename}.min${ext}`); // Write minified file fs.writeFileSync(minifiedPath, result.getObfuscatedCode()); // Calculate size reduction const originalSize = fs.statSync(filePath).size; const minifiedSize = fs.statSync(minifiedPath).size; const reduction = ((originalSize - minifiedSize) / originalSize * 100).toFixed(1); console.log(`✅ ${filePath} → ${minifiedPath} (${reduction}% smaller, obfuscated)`); return true; } catch (error) { console.error(`❌ Failed to obfuscate ${filePath}:`, error.message); return false; } } function processDirectory(dirPath) { if (!fs.existsSync(dirPath)) { console.log(`⚠️ Directory not found: ${dirPath}`); return; } const files = fs.readdirSync(dirPath); files.forEach(file => { const filePath = path.join(dirPath, file); const stat = fs.statSync(filePath); if (stat.isDirectory()) { processDirectory(filePath); } else if (stat.isFile()) { const ext = path.extname(file); if (extensions.includes(ext) && !shouldSkipFile(file)) { minifyFile(filePath); } } }); } async function main() { console.log('🚀 Starting JavaScript obfuscation and minification...\n'); let totalFiles = 0; let successFiles = 0; for (const dir of directories) { console.log(`📁 Processing directory: ${dir}`); processDirectory(dir); } console.log('\n✨ Obfuscation and minification complete!'); console.log('\n📝 To use obfuscated files, update your Blade templates:'); console.log(' - Replace .js with .min.js'); console.log(' - Example: '); console.log('\n🔒 Files are now obfuscated for better security!'); } // Run the script main().catch(console.error);