UNPKG

organ-ai-zer

Version:

AI-powered file organizer CLI tool

151 lines 6.71 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.FileOrganizer = void 0; const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); class FileOrganizer { async applySuggestions(suggestions, baseDirectory) { const sourceDirectories = new Set(); for (const suggestion of suggestions) { try { // Track source directories for cleanup const sourceDir = path.dirname(suggestion.file.path); sourceDirectories.add(sourceDir); await this.moveFile(suggestion, baseDirectory); console.log(`✅ Moved: ${suggestion.file.name}${suggestion.suggestedPath}`); } catch (error) { console.error(`❌ Failed to move ${suggestion.file.name}: ${error}`); } } // Clean up empty directories await this.cleanupEmptyDirectories(Array.from(sourceDirectories)); } async moveFile(suggestion, baseDirectory) { // Resolve target path relative to base directory const targetPath = baseDirectory ? path.resolve(baseDirectory, suggestion.suggestedPath) : path.resolve(suggestion.suggestedPath); const targetDir = path.dirname(targetPath); // Ensure target directory exists await fs.ensureDir(targetDir); // Check if target file already exists if (await fs.pathExists(targetPath)) { const newPath = await this.generateUniqueFilename(targetPath); suggestion.suggestedPath = path.relative(baseDirectory || process.cwd(), newPath); } // Move the file await fs.move(path.resolve(suggestion.file.path), targetPath); } async generateUniqueFilename(filePath) { const dir = path.dirname(filePath); const ext = path.extname(filePath); const name = path.basename(filePath, ext); let counter = 1; let newPath = filePath; while (await fs.pathExists(newPath)) { newPath = path.join(dir, `${name}_${counter}${ext}`); counter++; } return newPath; } async createBackup(directory) { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const resolvedDir = path.resolve(directory); const parentDir = path.dirname(resolvedDir); const dirName = path.basename(resolvedDir); const backupPath = path.join(parentDir, `backup_${dirName}_${timestamp}`); await fs.copy(directory, backupPath); return backupPath; } async cleanupEmptyDirectories(directories) { // Sort directories by depth (deepest first) to ensure we clean up child directories before parents const sortedDirectories = directories.sort((a, b) => b.split('/').length - a.split('/').length); for (const directory of sortedDirectories) { try { await this.cleanupEmptyDirectory(directory); } catch (error) { console.warn(`⚠️ Could not cleanup directory ${directory}: ${error}`); } } } async cleanupEmptyDirectory(directory) { try { // Check if directory exists if (!(await fs.pathExists(directory))) { return; } // Read directory contents const contents = await fs.readdir(directory); // If directory is empty, remove it if (contents.length === 0) { await fs.remove(directory); console.log(`🗑️ Removed empty directory: ${directory}`); // Recursively check parent directory const parentDir = path.dirname(directory); if (parentDir !== directory) { // Avoid infinite recursion at root await this.cleanupEmptyDirectory(parentDir); } } // If directory only contains hidden files (like .DS_Store), we might want to remove it too else if (contents.every(item => item.startsWith('.'))) { // Only remove if all files are common system files const systemFiles = ['.DS_Store', '.Thumbs.db', 'desktop.ini']; if (contents.every(item => systemFiles.includes(item))) { // Remove system files first for (const file of contents) { await fs.remove(path.join(directory, file)); } // Then remove the directory await fs.remove(directory); console.log(`🗑️ Removed directory with only system files: ${directory}`); // Recursively check parent directory const parentDir = path.dirname(directory); if (parentDir !== directory) { await this.cleanupEmptyDirectory(parentDir); } } } } catch (error) { // Silently ignore errors during cleanup - it's not critical console.warn(`⚠️ Could not cleanup directory ${directory}: ${error}`); } } } exports.FileOrganizer = FileOrganizer; //# sourceMappingURL=file-organizer.js.map