#!/usr/bin/env node import * as fs from 'fs'; import * as path from 'path'; import { execSync } from 'child_process'; interface CleanupPlan { directories: string[]; files: string[]; backupPath?: string; totalSize: number; } class LegacyCleanup { private repoRoot: string; private vezaDocsRoot: string; private reportsDir: string; constructor(repoRoot: string) { this.repoRoot = repoRoot; this.vezaDocsRoot = path.join(repoRoot, 'veza-docs'); this.reportsDir = path.join(this.vezaDocsRoot, '_reports'); console.log(`Repo root: ${this.repoRoot}`); console.log(`Veza docs root: ${this.vezaDocsRoot}`); console.log(`Reports dir: ${this.reportsDir}`); } async createCleanupPlan(): Promise { console.log('📋 CrĂ©ation du plan de nettoyage...'); // Lire la liste des dossiers legacy const legacyDirsPath = path.join(this.reportsDir, 'legacy_doc_dirs.json'); console.log(`Recherche du fichier: ${legacyDirsPath}`); if (!fs.existsSync(legacyDirsPath)) { throw new Error(`Fichier legacy_doc_dirs.json manquant Ă  ${legacyDirsPath}. ExĂ©cutez d'abord le scan global.`); } const legacyData = JSON.parse(fs.readFileSync(legacyDirsPath, 'utf-8')); // Filtrer les dossiers Ă  nettoyer (exclure veza-docs-backup pour l'instant) const directoriesToClean = legacyData.legacyDirs.filter((dir: string) => !dir.includes('veza-docs-backup') && !dir.includes('node_modules') && !dir.includes('.git') && !dir.includes('dist') && !dir.includes('build') ); // Calculer la taille totale let totalSize = 0; const filesToClean: string[] = []; for (const dir of directoriesToClean) { const fullPath = path.join(this.repoRoot, dir); if (fs.existsSync(fullPath)) { const stats = this.getDirSize(fullPath); totalSize += stats.size; filesToClean.push(...stats.files); } } const plan: CleanupPlan = { directories: directoriesToClean, files: filesToClean, totalSize }; // CrĂ©er un backup si demandĂ© if (process.argv.includes('--backup')) { plan.backupPath = await this.createBackup(plan); } return plan; } private getDirSize(dirPath: string): { size: number; files: string[] } { let totalSize = 0; const files: string[] = []; const walkDir = (currentPath: string) => { const items = fs.readdirSync(currentPath); for (const item of items) { const itemPath = path.join(currentPath, item); const stats = fs.statSync(itemPath); if (stats.isDirectory()) { walkDir(itemPath); } else { totalSize += stats.size; files.push(itemPath); } } }; walkDir(dirPath); return { size: totalSize, files }; } private async createBackup(plan: CleanupPlan): Promise { console.log('đŸ’Ÿ CrĂ©ation du backup...'); const backupPath = path.join(this.reportsDir, 'legacy_docs_backup.tar.gz'); try { // CrĂ©er un tar.gz des dossiers Ă  nettoyer const dirsToBackup = plan.directories.join(' '); const command = `cd "${this.repoRoot}" && tar -czf "${backupPath}" ${dirsToBackup}`; execSync(command, { stdio: 'pipe' }); console.log(`✅ Backup créé: ${backupPath}`); return backupPath; } catch (error) { console.warn('⚠ Impossible de crĂ©er le backup:', error); return ''; } } async generateCleanupReport(plan: CleanupPlan): Promise { console.log('📊 GĂ©nĂ©ration du rapport de nettoyage...'); const sizeMB = Math.round(plan.totalSize / (1024 * 1024) * 100) / 100; let md = `# đŸ§č Plan de Nettoyage - Documentation Veza\n\n`; md += `**Date** : ${new Date().toLocaleDateString('fr-FR')}\n\n`; md += `## 📊 RĂ©sumĂ©\n\n`; md += `- **Dossiers Ă  nettoyer** : ${plan.directories.length}\n`; md += `- **Fichiers Ă  supprimer** : ${plan.files.length}\n`; md += `- **Taille totale** : ${sizeMB} MB\n`; if (plan.backupPath) { md += `- **Backup créé** : \`${plan.backupPath}\`\n`; } md += `\n`; md += `## 📁 Dossiers Ă  Supprimer\n\n`; md += `| Dossier | Taille | Fichiers |\n`; md += `|---------|--------|----------|\n`; for (const dir of plan.directories) { const fullPath = path.join(this.repoRoot, dir); if (fs.existsSync(fullPath)) { const stats = this.getDirSize(fullPath); const dirSizeMB = Math.round(stats.size / (1024 * 1024) * 100) / 100; md += `| \`${dir}\` | ${dirSizeMB} MB | ${stats.files.length} |\n`; } } md += `\n## ⚠ Avertissements\n\n`; md += `- **VĂ©rifiez** que tous les fichiers importants ont Ă©tĂ© migrĂ©s vers \`veza-docs/\`\n`; md += `- **Sauvegardez** vos donnĂ©es avant d'appliquer le nettoyage\n`; md += `- **Testez** le build aprĂšs nettoyage : \`npm run build\`\n\n`; md += `## 🚀 Commandes de Nettoyage\n\n`; md += `\`\`\`bash\n`; md += `# Dry-run (simulation)\n`; md += `npx ts-node scripts/cleanup_legacy.ts --dry-run\n\n`; md += `# Application rĂ©elle\n`; md += `npx ts-node scripts/cleanup_legacy.ts --apply\n`; md += `\`\`\`\n`; fs.writeFileSync( path.join(this.reportsDir, 'cleanup_plan.md'), md ); // Sauvegarder le plan en JSON fs.writeFileSync( path.join(this.reportsDir, 'cleanup_plan.json'), JSON.stringify(plan, null, 2) ); console.log('✅ Rapport de nettoyage gĂ©nĂ©rĂ©'); } async dryRun(): Promise { console.log('🔍 Simulation du nettoyage (dry-run)...'); const plan = await this.createCleanupPlan(); await this.generateCleanupReport(plan); console.log('📋 Plan de nettoyage créé:'); console.log(` - ${plan.directories.length} dossiers Ă  supprimer`); console.log(` - ${plan.files.length} fichiers Ă  supprimer`); console.log(` - ${Math.round(plan.totalSize / (1024 * 1024) * 100) / 100} MB Ă  libĂ©rer`); if (plan.backupPath) { console.log(` - Backup: ${plan.backupPath}`); } } async apply(): Promise { console.log('đŸ§č Application du nettoyage...'); // VĂ©rifier que le plan existe const planPath = path.join(this.reportsDir, 'cleanup_plan.json'); if (!fs.existsSync(planPath)) { throw new Error('Plan de nettoyage manquant. ExĂ©cutez d\'abord --dry-run'); } const plan: CleanupPlan = JSON.parse(fs.readFileSync(planPath, 'utf-8')); console.log(`đŸ—‘ïž Suppression de ${plan.directories.length} dossiers...`); let deletedCount = 0; let errorCount = 0; for (const dir of plan.directories) { const fullPath = path.join(this.repoRoot, dir); if (fs.existsSync(fullPath)) { try { fs.rmSync(fullPath, { recursive: true, force: true }); console.log(` ✅ SupprimĂ©: ${dir}`); deletedCount++; } catch (error) { console.error(` ❌ Erreur: ${dir} - ${error}`); errorCount++; } } else { console.log(` ⚠ DĂ©jĂ  supprimĂ©: ${dir}`); } } console.log(`\n📊 RĂ©sultat:`); console.log(` - Dossiers supprimĂ©s: ${deletedCount}`); console.log(` - Erreurs: ${errorCount}`); // VĂ©rifier le build aprĂšs nettoyage console.log('\n🔍 VĂ©rification du build aprĂšs nettoyage...'); try { execSync('npm run build', { cwd: this.vezaDocsRoot, stdio: 'pipe' }); console.log('✅ Build rĂ©ussi aprĂšs nettoyage'); } catch (error) { console.error('❌ Build Ă©chouĂ© aprĂšs nettoyage:', error); throw new Error('Le build a Ă©chouĂ© aprĂšs nettoyage. VĂ©rifiez les fichiers supprimĂ©s.'); } } async run(): Promise { const args = process.argv.slice(2); if (args.includes('--dry-run')) { await this.dryRun(); } else if (args.includes('--apply')) { await this.apply(); } else { console.log('Usage:'); console.log(' --dry-run : Simulation du nettoyage'); console.log(' --apply : Application du nettoyage'); console.log(' --backup : CrĂ©er un backup (avec --dry-run)'); } } } // ExĂ©cution du script if (require.main === module) { // Trouver le premier argument qui n'est pas un flag et qui n'est pas ts-node const args = process.argv.slice(2); // Ignorer 'ts-node' et le nom du script const repoRoot = args.find(arg => !arg.startsWith('--')) || path.join(__dirname, '../..'); const cleanup = new LegacyCleanup(repoRoot); cleanup.run(); } export { LegacyCleanup };