Files
peakskills/scripts/sync-skills.ts
Julien Froidefond 9d11a725d7 fix: clean up admin exports and enhance skill category structure
- Removed unused export for management pages in admin index.
- Added id and name properties to skills being synced from JSON, improving data integrity for skill categories.
2025-08-26 13:06:43 +02:00

163 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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<void> {
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<string, Skill>();
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);
// Utiliser bulkInsertSkillsFromJSON qui gère les conflits automatiquement
const needsUpdate = existingSkill
? existingSkill.description !== skillFromFile.description ||
existingSkill.icon !== skillFromFile.icon ||
JSON.stringify(existingSkill.links?.sort()) !==
JSON.stringify(skillFromFile.links?.sort())
: true;
if (!existingSkill) {
console.log(
` Nouvelle skill: ${skillFromFile.name} (${skillFromFile.id})`
);
stats.newSkills++;
} else if (needsUpdate) {
console.log(
` 🔄 Mise à jour de la skill: ${skillFromFile.name} (${skillFromFile.id})`
);
stats.updatedSkills++;
} else {
console.log(
` ✅ Skill inchangée: ${skillFromFile.name} (${skillFromFile.id})`
);
stats.skippedSkills++;
}
// Insérer/mettre à jour la skill (bulkInsert gère les conflits)
await SkillsService.bulkInsertSkillsFromJSON([
{
id: categoryFromFile.category.toLowerCase(),
name: categoryFromFile.category,
category: categoryFromFile.category,
icon: categoryFromFile.icon,
skills: [skillFromFile],
},
]);
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 };