UNPKG

@nntdgrss/node-modules-cleaner

Version:

Утилита для поиска и удаления неиспользуемых node_modules директорий

131 lines (130 loc) 5.33 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FileUtils = void 0; const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const glob_1 = require("glob"); const logger_utils_1 = require("./logger.utils"); /** * Класс для работы с файловой системой */ class FileUtils { /** * Поиск всех директорий node_modules в указанной директории * @param config - конфигурация поиска * @returns Promise<NodeModulesInfo[]> - массив информации о найденных директориях */ static async findNodeModules(config) { try { const pattern = path_1.default.join(config.startPath, config.maxDepth === -1 ? "**/node_modules" : `${"*/".repeat(config.maxDepth)}node_modules`); let paths = await (0, glob_1.glob)(pattern, { ignore: config.exclude, absolute: true, }); // Фильтруем вложенные node_modules paths = paths.filter((p) => { const relativePath = p.substring(config.startPath.length); const count = relativePath .split("/") .filter((part) => part === "node_modules").length; return count === 1; }); logger_utils_1.Logger.info(`Найдено ${paths.length} директорий node_modules`); const results = []; let processed = 0; for (const nodePath of paths) { try { const stats = await fs_extra_1.default.stat(nodePath); const size = await this.getDirectorySize(nodePath); const lastModified = stats.mtime; const isUnused = this.isDirectoryUnused(lastModified); results.push({ path: nodePath, size, lastModified, isUnused, }); processed++; logger_utils_1.Logger.progress(processed, paths.length, "Анализ директорий"); } catch (err) { logger_utils_1.Logger.warn(`Ошибка при обработке ${nodePath}: ${err}`); } } return results; } catch (err) { logger_utils_1.Logger.error(`Ошибка при поиске node_modules: ${err}`); return []; } } /** * Получение размера директории * @param dirPath - путь к директории * @returns Promise<number> - размер в байтах */ static async getDirectorySize(dirPath) { try { const files = await fs_extra_1.default.readdir(dirPath); const stats = await Promise.all(files.map(async (file) => { const filePath = path_1.default.join(dirPath, file); const stat = await fs_extra_1.default.stat(filePath); if (stat.isDirectory()) { return this.getDirectorySize(filePath); } return stat.size; })); return stats.reduce((acc, size) => acc + size, 0); } catch (err) { logger_utils_1.Logger.warn(`Ошибка при подсчете размера ${dirPath}: ${err}`); return 0; } } /** * Проверка, является ли директория неиспользуемой (старше 1 месяца) * @param lastModified - дата последнего изменения * @returns boolean */ static isDirectoryUnused(lastModified) { const oneMonthAgo = new Date(); oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1); return lastModified < oneMonthAgo; } /** * Удаление директории node_modules * @param path - путь к директории * @returns Promise<boolean> - успешность удаления */ static async removeNodeModules(path) { try { await fs_extra_1.default.remove(path); return true; } catch (err) { logger_utils_1.Logger.error(`Ошибка при удалении ${path}: ${err}`); return false; } } /** * Форматирование размера в читаемый вид * @param bytes - размер в байтах * @returns string - отформатированный размер */ static formatSize(bytes) { const units = ["Б", "КБ", "МБ", "ГБ"]; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return `${size.toFixed(2)} ${units[unitIndex]}`; } } exports.FileUtils = FileUtils;