#!/usr/bin/env tsx import { SkillsService } from "../services/skills-service"; import { loadSkillCategoriesFromFiles } from "../lib/skill-file-loader"; import { SkillCategory, Skill } from "../lib/types"; interface SyncStats { categoriesProcessed: number; skillsProcessed: number; newSkills: number; updatedSkills: number; skippedSkills: number; } /** * Synchronise les skills depuis les fichiers JSON vers la base de données * - Préserve les skills existantes (ne modifie que description/image) * - Ajoute uniquement les nouvelles skills * - Ne supprime jamais de skills */ async function syncSkillsToDatabase(): Promise { try { console.log("🚀 Démarrage de la synchronisation des skills..."); // Charger les skills depuis les fichiers JSON const skillCategoriesFromFiles = loadSkillCategoriesFromFiles(); console.log(`📁 ${skillCategoriesFromFiles.length} catégories trouvées dans les fichiers`); // Récupérer les skills existantes de la base de données const existingCategories = await SkillsService.getSkillCategories(); console.log(`💾 ${existingCategories.length} catégories existantes en base`); // Créer un map des skills existantes pour une recherche rapide const existingSkillsMap = new Map(); existingCategories.forEach(category => { category.skills.forEach(skill => { existingSkillsMap.set(skill.id, skill); }); }); console.log(`🔍 ${existingSkillsMap.size} skills existantes détectées`); const stats: SyncStats = { categoriesProcessed: 0, skillsProcessed: 0, newSkills: 0, updatedSkills: 0, skippedSkills: 0 }; // Synchroniser chaque catégorie for (const categoryFromFile of skillCategoriesFromFiles) { console.log(`\n📂 Traitement de la catégorie: ${categoryFromFile.category}`); const categoryId = categoryFromFile.category.toLowerCase(); // Vérifier si la catégorie existe, sinon la créer const existingCategory = existingCategories.find(cat => cat.category.toLowerCase() === categoryFromFile.category.toLowerCase() ); if (!existingCategory) { console.log(` ➕ Création de la nouvelle catégorie: ${categoryFromFile.category}`); await SkillsService.createSkillCategory({ id: categoryId, name: categoryFromFile.category, icon: categoryFromFile.icon }); } // Synchroniser les skills de cette catégorie for (const skillFromFile of categoryFromFile.skills) { const existingSkill = existingSkillsMap.get(skillFromFile.id); if (!existingSkill) { // Nouvelle skill - l'ajouter console.log(` ➕ Nouvelle skill: ${skillFromFile.name} (${skillFromFile.id})`); await SkillsService.createSkill({ id: skillFromFile.id, name: skillFromFile.name, description: skillFromFile.description, icon: skillFromFile.icon, categoryId: categoryId, links: skillFromFile.links || [] }); stats.newSkills++; } else { // Skill existante - vérifier s'il faut mettre à jour description/icon/links const needsUpdate = existingSkill.description !== skillFromFile.description || existingSkill.icon !== skillFromFile.icon || JSON.stringify(existingSkill.links?.sort()) !== JSON.stringify(skillFromFile.links?.sort()); if (needsUpdate) { console.log(` 🔄 Mise à jour de la skill: ${skillFromFile.name} (${skillFromFile.id})`); // Utiliser la méthode bulkInsert avec une seule catégorie/skill pour la mise à jour await SkillsService.bulkInsertSkillsFromJSON([{ category: categoryFromFile.category, icon: categoryFromFile.icon, skills: [skillFromFile] }]); stats.updatedSkills++; } else { console.log(` ✅ Skill inchangée: ${skillFromFile.name} (${skillFromFile.id})`); stats.skippedSkills++; } } stats.skillsProcessed++; } stats.categoriesProcessed++; } // Afficher les statistiques finales console.log("\n📊 Statistiques de synchronisation:"); console.log(` • Catégories traitées: ${stats.categoriesProcessed}`); console.log(` • Skills traitées: ${stats.skillsProcessed}`); console.log(` • Nouvelles skills: ${stats.newSkills}`); console.log(` • Skills mises à jour: ${stats.updatedSkills}`); console.log(` • Skills inchangées: ${stats.skippedSkills}`); // Vérification finale const finalCategories = await SkillsService.getSkillCategories(); const totalSkillsInDb = finalCategories.reduce((sum, cat) => sum + cat.skills.length, 0); console.log(`\n✅ Synchronisation terminée avec succès!`); console.log(`💾 Total skills en base: ${totalSkillsInDb}`); } catch (error) { console.error("❌ Erreur lors de la synchronisation:", error); process.exit(1); } } // Exécuter le script si appelé directement if (require.main === module) { syncSkillsToDatabase() .then(() => { console.log("🎉 Script terminé avec succès"); process.exit(0); }) .catch((error) => { console.error("💥 Erreur fatale:", error); process.exit(1); }); } export { syncSkillsToDatabase };