veza/veza-docs/scripts/cleanup_legacy.ts

266 lines
8.5 KiB
TypeScript

#!/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<CleanupPlan> {
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<string> {
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<void> {
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<void> {
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<void> {
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<void> {
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 };