2025-03-25 09:02:03 +01:00
|
|
|
import fs from "fs-extra";
|
|
|
|
import path from "path";
|
2025-03-27 00:00:41 +01:00
|
|
|
import type { Dirent } from "fs-extra";
|
|
|
|
import { execSync } from "node:child_process";
|
2025-03-25 09:02:03 +01:00
|
|
|
|
2025-03-26 09:26:22 +01:00
|
|
|
/**
|
|
|
|
* Example usage with node >= v22:
|
2025-03-27 00:00:41 +01:00
|
|
|
* node --experimental-strip-types bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
|
2025-03-26 09:26:22 +01:00
|
|
|
* Example usage with tsx:
|
2025-03-27 00:00:41 +01:00
|
|
|
* tsx bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
|
2025-03-26 09:26:22 +01:00
|
|
|
*/
|
2025-03-25 09:02:03 +01:00
|
|
|
function main() {
|
2025-03-27 00:00:41 +01:00
|
|
|
|
|
|
|
if (process.argv.length > 4 || process.argv.length < 3) {
|
|
|
|
console.error("Usage: cleanupNodeModules.ts [path-to-build-folder] [--skip-prune-dev-deps]");
|
2025-03-25 09:02:03 +01:00
|
|
|
process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const basePath = process.argv[2];
|
2025-03-27 00:00:41 +01:00
|
|
|
const pruneDevDeps = process.argv[3] !== "--skip-prune-dev-deps";
|
2025-03-25 09:02:03 +01:00
|
|
|
|
|
|
|
if (!fs.existsSync(basePath)) {
|
2025-03-27 00:00:41 +01:00
|
|
|
console.error(`Supplied path '${basePath}' does not exist. Aborting.`);
|
2025-03-25 09:02:03 +01:00
|
|
|
process.exit(1);
|
|
|
|
}
|
2025-03-27 00:00:41 +01:00
|
|
|
|
|
|
|
console.log(`Starting pruning of node_modules ${!pruneDevDeps ? '(skipping npm pruning)' : ''} in '${basePath}'...`);
|
|
|
|
cleanupNodeModules(basePath, pruneDevDeps);
|
|
|
|
console.log("Successfully pruned node_modules.");
|
2025-03-25 09:02:03 +01:00
|
|
|
}
|
|
|
|
|
2025-03-27 00:00:41 +01:00
|
|
|
function cleanupNodeModules(basePath: string, pruneDevDeps: boolean = true) {
|
|
|
|
|
2025-03-26 09:18:16 +01:00
|
|
|
const nodeModulesDirPath = path.join(basePath, "node_modules");
|
|
|
|
const nodeModulesContent = fs.readdirSync(nodeModulesDirPath, { recursive: true, withFileTypes: true });
|
2025-03-25 09:02:03 +01:00
|
|
|
//const libDir = fs.readdirSync(path.join(basePath, "./libraries"), { recursive: true, withFileTypes: true });
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete unnecessary folders
|
|
|
|
*/
|
|
|
|
const filterableDirs = new Set([
|
|
|
|
"demo",
|
|
|
|
"demos",
|
|
|
|
"doc",
|
|
|
|
"docs",
|
|
|
|
"example",
|
|
|
|
"examples",
|
|
|
|
"test",
|
|
|
|
"tests"
|
|
|
|
]);
|
|
|
|
|
2025-03-26 09:12:22 +01:00
|
|
|
nodeModulesContent
|
2025-03-25 09:02:03 +01:00
|
|
|
.filter(el => el.isDirectory() && filterableDirs.has(el.name))
|
2025-03-26 09:47:06 +01:00
|
|
|
.forEach(dir => removeDirent(dir));
|
2025-03-25 09:02:03 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete unnecessary files based on file extension
|
|
|
|
* TODO filter out useless (README).md files
|
|
|
|
*/
|
|
|
|
const filterableFileExt = new Set([
|
|
|
|
"ts",
|
|
|
|
"map"
|
|
|
|
]);
|
|
|
|
|
2025-03-26 09:12:22 +01:00
|
|
|
nodeModulesContent
|
2025-03-25 09:02:03 +01:00
|
|
|
// TriliumNextTODO: check if we can improve this naive file ext matching, without introducing any additional dependency
|
|
|
|
.filter(el => el.isFile() && filterableFileExt.has(el.name.split(".").at(-1) || ""))
|
2025-03-26 09:47:06 +01:00
|
|
|
.forEach(dir => removeDirent(dir));
|
2025-03-25 09:02:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete specific unnecessary folders
|
|
|
|
* TODO: check if we want removeSync to throw an error, if path does not exist anymore -> currently it will silently fail
|
|
|
|
*/
|
|
|
|
const extraFoldersDelete = new Set([
|
2025-03-26 09:28:50 +01:00
|
|
|
path.join(nodeModulesDirPath, ".bin"),
|
2025-03-26 09:18:16 +01:00
|
|
|
path.join(nodeModulesDirPath, "@excalidraw", "excalidraw", "dist", "dev"),
|
|
|
|
path.join(nodeModulesDirPath, "boxicons", "svg"),
|
|
|
|
path.join(nodeModulesDirPath, "boxicons", "node_modules"),
|
|
|
|
path.join(nodeModulesDirPath, "boxicons", "src"),
|
|
|
|
path.join(nodeModulesDirPath, "boxicons", "iconjar"),
|
|
|
|
path.join(nodeModulesDirPath, "@jimp", "plugin-print", "fonts"),
|
|
|
|
path.join(nodeModulesDirPath, "jimp", "dist", "browser") // missing "@" in front of jimp is not a typo here
|
2025-03-25 09:02:03 +01:00
|
|
|
]);
|
|
|
|
|
2025-03-26 09:12:22 +01:00
|
|
|
nodeModulesContent
|
2025-03-25 09:02:03 +01:00
|
|
|
.filter(el => el.isDirectory() && extraFoldersDelete.has(path.join(el.parentPath, el.name)))
|
2025-03-26 09:47:06 +01:00
|
|
|
.forEach(dir => removeDirent(dir))
|
|
|
|
}
|
|
|
|
|
2025-03-27 00:00:41 +01:00
|
|
|
|
2025-03-26 09:47:06 +01:00
|
|
|
function removeDirent(el: Dirent) {
|
|
|
|
const elementToDelete = path.join(el.parentPath, el.name);
|
|
|
|
fs.removeSync(elementToDelete);
|
|
|
|
|
|
|
|
if (process.env.VERBOSE) {
|
|
|
|
console.log(`Deleted ${elementToDelete}`);
|
|
|
|
}
|
|
|
|
|
2025-03-25 09:02:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
main()
|