refactor: update database setup and remove skills migration API

- Changed migration commands in DATABASE_SETUP.md to use `pnpm run sync-skills` and `pnpm run sync-teams`.
- Removed the skills migration API endpoint in route.ts, streamlining the migration process.
- Updated MIGRATION_UUID.md to reflect changes in migration steps and removed the old skills migration script.
- Added new sync scripts for skills and teams in package.json.
- Cleaned up init.sql by removing old teams data insertion and adjusted comments for clarity.
This commit is contained in:
Julien Froidefond
2025-08-21 15:21:36 +02:00
parent dad172157b
commit a4b680b092
11 changed files with 317 additions and 205 deletions

149
scripts/sync-skills.ts Normal file
View File

@@ -0,0 +1,149 @@
#!/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);
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 };