cyberchef/scripts/postinstall.mjs
consigcody94 1ac3190dae Modernize CyberChef build system, dependencies, UI, and testing
Build System:
- Replace Grunt with npm scripts and Node.js helper scripts
- Remove worker-loader, use native Webpack 5 worker syntax
- Add Rspack config as faster alternative bundler (5-23x faster)
- Replace platform-specific sed postinstall hacks with cross-platform Node.js script
- Update browser targets from Chrome 50/Firefox 38 to Chrome 80/Firefox 78/Safari 14
- Fix import assertions (assert -> with) for Node 24 compatibility

Dependencies:
- Replace deprecated crypto-js with native RC4 implementation and @noble/hashes EVP KDF
- Replace blakejs with @noble/hashes/blake2b and blake2s
- Add @noble/hashes for MD5, SHA1/2/3, RIPEMD160, HMAC, HKDF (crypto-api fallback for legacy algos)
- Replace lodash with native CaseConvert.mjs utility
- Replace moment.js in web layer with date-fns
- Add date-fns and date-fns-tz dependencies
- Remove jquery, snackbarjs, arrive, bootstrap-colorpicker, bootstrap-material-design, popper.js v1, lodash, blakejs, crypto-js

UI Modernization:
- Upgrade Bootstrap 4.6.2 to Bootstrap 5.3 (87 data attribute renames)
- Remove bootstrap-material-design (unmaintained)
- Remove jQuery dependency entirely (38 calls replaced with native DOM + BS5 JS API)
- Add custom Snackbar.mjs notification utility (replaces snackbarjs)
- Replace bootstrap-colorpicker with native HTML color input

Testing:
- Add Vitest config and adapter for running existing TestRegister tests
- Add Playwright config and E2E test replacing Nightwatch
- Update CI workflows to use npm scripts and Playwright
2026-03-23 13:59:24 -04:00

82 lines
2.6 KiB
JavaScript

/**
* Cross-platform postinstall script.
* Fixes known issues in dependencies without requiring platform-specific `sed`.
* Replaces Grunt exec:fixCryptoApiImports and exec:fixSnackbarMarkup.
*
* @author CyberChef Modernization
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import { readFileSync, writeFileSync, readdirSync, statSync } from "fs";
import { join, extname } from "path";
/**
* Recursively find all files in a directory.
*/
function findFiles(dir, files = []) {
try {
const entries = readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = join(dir, entry.name);
if (entry.isDirectory() && entry.name !== ".git") {
findFiles(fullPath, files);
} else if (entry.isFile()) {
files.push(fullPath);
}
}
} catch {
// Directory may not exist
}
return files;
}
// Fix 1: crypto-api imports - add .mjs extensions to relative imports
console.log("Fixing crypto-api imports...");
const cryptoApiDir = join("node_modules", "crypto-api", "src");
let cryptoApiFixed = 0;
try {
const files = findFiles(cryptoApiDir);
for (const file of files) {
let content = readFileSync(file, "utf8");
const original = content;
// Add .mjs extension to relative imports that don't already have it
content = content.replace(/from\s+"(\.[^"]*?)(?<!\.mjs)";/g, (match, importPath) => {
// Don't add .mjs if it already has a file extension
if (extname(importPath) !== "") return match;
return `from "${importPath}.mjs";`;
});
if (content !== original) {
writeFileSync(file, content);
cryptoApiFixed++;
}
}
console.log(` Fixed ${cryptoApiFixed} files in crypto-api.`);
} catch (e) {
console.log(` Skipping crypto-api fix (not installed or not found): ${e.message}`);
}
// Fix 2: snackbarjs - fix self-closing div
console.log("Fixing snackbarjs markup...");
const snackbarFile = join("node_modules", "snackbarjs", "src", "snackbar.js");
try {
let content = readFileSync(snackbarFile, "utf8");
const original = content;
content = content.replace(/<div id=snackbar-container\/>/g, "<div id=snackbar-container>");
if (content !== original) {
writeFileSync(snackbarFile, content);
console.log(" Fixed snackbarjs self-closing div.");
} else {
console.log(" snackbarjs already fixed or pattern not found.");
}
} catch (e) {
console.log(` Skipping snackbarjs fix (not installed or not found): ${e.message}`);
}
console.log("Postinstall complete.");