docs: add backend documentation files

Reference guides (Sequelize model methods, Swagger) and migration reports
from the MongoDB-to-MySQL and domain-based route structure migrations.
This commit is contained in:
2026-04-26 16:54:56 +02:00
parent 83216e96be
commit 097e11be1b
9 changed files with 2116 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
# Méthodes disponibles sur l'objet `Article` (Sequelize)
Ce document liste toutes les méthodes automatiquement générées par Sequelize pour le modèle `Article` en fonction des associations définies dans `src/database/relationships/index.js`.
---
## Associations Many-to-Many (belongsToMany)
### 1. **Tags** via `TagList`
Association alias: `articleTags`
Clés: `foreignKey: "articleId"`, `otherKey: "tagName"`
```javascript
article.getArticleTags() // Récupère tous les tags
article.setArticleTags([...]) // Définit les tags
article.addArticleTag(tag) // Ajoute un tag
article.addArticleTags([...]) // Ajoute plusieurs tags
article.removeArticleTag(tag) // Retire un tag
article.removeArticleTags([...]) // Retire plusieurs tags
article.countArticleTags() // Compte les tags
article.hasArticleTag(tag) // Vérifie si le tag est lié
article.hasArticleTags([...]) // Vérifie si les tags sont liés
// Alias généré par Sequelize (correspond à belongsToMany):
// Nom de la clé étrangère singularisée + pluralisé = "ArticleTag(s)" => "addTagList", "getTagList", etc.
article.addTagList(tag) // Ajoute un tag via l'alias
article.addTagLists([...]) // Ajoute plusieurs tags via l'alias
article.getTagLists() // Récupère les tags via l'alias
article.setTagLists([...]) // Définit les tags via l'alias
article.removeTagList(tag) // Retire un tag via l'alias
article.removeTagLists([...]) // Retire plusieurs tags via l'alias
article.countTagLists() // Compte les tags via l'alias
article.hasTagList(tag) // Vérifie si le tag est lié via l'alias
article.hasTagLists([...]) // Vérifie si les tags sont liés via l'alias
```
### 2. **Users (Favoris)** via `Favorite`
Association alias: `articleFavoriteUsers`
Clés: `foreignKey: "articleId"`, `otherKey: "userId"`
```javascript
article.getArticleFavoriteUsers() // Récupère les utilisateurs qui ont favorisé
article.setArticleFavoriteUsers([...]) // Définit les utilisateurs
article.addUserIdUser(user) // Ajoute un utilisateur
article.addArticleFavoriteUsers([...]) // Ajoute plusieurs utilisateurs
article.removeUserIdUser(user) // Retire un utilisateur
article.removeArticleFavoriteUsers([...]) // Retire plusieurs utilisateurs
article.countArticleFavoriteUsers() // Compte les utilisateurs
article.hasUserIdUser(user) // Vérifie si l'utilisateur a favorisé
article.hasArticleFavoriteUsers([...]) // Vérifie si les utilisateurs ont favorisé
```
---
## Associations One-to-Many (hasMany)
### 3. **Comments**
Association alias: `comments`
Clé étrangère: `articleId`
```javascript
article.getComments() // Récupère tous les commentaires
article.setComments([...]) // Définit les commentaires
article.addComment(comment) // Crée/ajoute un commentaire
article.addComments([...]) // Ajoute plusieurs commentaires
article.removeComment(comment) // Retire un commentaire
article.removeComments([...]) // Retire plusieurs commentaires
article.countComments() // Compte les commentaires
article.hasComment(comment) // Vérifie si le commentaire existe
article.hasComments([...]) // Vérifie si les commentaires existent
article.createComment({...}) // Crée un nouveau commentaire
```
### 4. **Favorites** (enregistrements de join)
Association alias: `favorites`
Clé étrangère: `articleId`
```javascript
article.getFavorites() // Récupère les enregistrements Favorite
article.setFavorites([...]) // Définit les favoris
article.addFavorite(favorite) // Ajoute un enregistrement Favorite
article.addFavorites([...]) // Ajoute plusieurs enregistrements
article.removeFavorite(favorite) // Retire un enregistrement Favorite
article.removeFavorites([...]) // Retire plusieurs enregistrements
article.countFavorites() // Compte les enregistrements Favorite
article.hasFavorite(favorite) // Vérifie si le Favorite existe
article.hasFavorites([...]) // Vérifie si les Favorites existent
article.createFavorite({...}) // Crée un nouveau Favorite
```
### 5. **TagLists** (enregistrements de join)
Association alias: `tagLists`
Clé étrangère: `articleId`
```javascript
article.getTagLists() // Récupère les enregistrements TagList
article.setTagLists([...]) // Définit les TagList
article.addTagList(tagList) // Ajoute un enregistrement TagList
article.addTagLists([...]) // Ajoute plusieurs enregistrements
article.removeTagList(tagList) // Retire un enregistrement TagList
article.removeTagLists([...]) // Retire plusieurs enregistrements
article.countTagLists() // Compte les enregistrements TagList
article.hasTagList(tagList) // Vérifie si le TagList existe
article.hasTagLists([...]) // Vérifie si les TagLists existent
article.createTagList({...}) // Crée un nouveau TagList
```
---
## Associations Belongs-To (hasOne inverse)
### 6. **Author (User)**
Association alias: `author`
Clé étrangère: `authorId`
```javascript
article.getAuthor() // Récupère l'auteur
article.setAuthor(user) // Définit l'auteur
article.createAuthor({...}) // Crée un nouvel auteur
```
---
## Méthodes personnalisées du modèle
### Méthodes d'instance définies dans `Article.js` :
```javascript
article.toJSONFor() // Retourne un objet JSON formaté
// Format: { id, slug, title, description, body }
```
---
## Hooks (Triggers)
```javascript
Article.beforeValidate() // Déclenché avant la validation
// Génère automatiquement un slug basé sur le titre
// Format: slug(`${article.title}`) + '-' + random
```
---
## Exemples d'utilisation concrets
### Ajouter des tags à un article
```javascript
const article = await Article.findByPk(1);
const tag = await Tag.findByPk('javascript');
await article.addTagList(tag); // Via alias
// ou
await article.addArticleTag(tag); // Via alias généré automatiquement
```
### Récupérer les commentaires d'un article
```javascript
const article = await Article.findByPk(1);
const comments = await article.getComments();
```
### Obtenir les utilisateurs qui ont favorisé cet article
```javascript
const article = await Article.findByPk(1);
const fans = await article.getArticleFavoriteUsers();
```
### Créer un commentaire pour un article
```javascript
const article = await Article.findByPk(1);
const comment = await article.createComment({
body: "Great article!",
authorId: userId
});
```
### Compter les tags
```javascript
const article = await Article.findByPk(1);
const tagCount = await article.countTagLists();
```
---
## Notes importantes
1. **Noms des méthodes générées** : Sequelize génère les noms en fonction du nom de l'association (alias) ou du modèle.
- Si alias est `articleTags``getArticleTags()`, `addArticleTag()`, etc.
- Si alias est `tagLists``getTagLists()`, `addTagList()`, etc.
2. **Singulier/Pluriel** : Les méthodes `add*` acceptent soit un seul élément (singulier) soit un tableau (pluriel).
3. **Paramètres optionnels** : La plupart des méthodes `get*` acceptent un paramètre `options` pour personnaliser la requête :
```javascript
article.getComments({
where: { createdAt: { [Op.gte]: someDate } },
limit: 10,
offset: 0,
order: [['createdAt', 'DESC']]
});
```
4. **Transactions** : Toutes les opérations CRUD peuvent être encapsulées dans une transaction :
```javascript
const transaction = await sequelize.transaction();
await article.addTagList(tag, { transaction });
await transaction.commit();
```
5. **Alias vs Nom généré** : L'alias défini dans la relation détermine le nom des méthodes générées. Dans ce projet, les alias comme `articleTags`, `tagLists` permettent d'appeler `getTagLists()`, `addTagList()`, etc.
+328
View File
@@ -0,0 +1,328 @@
╔═══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ✅ MIGRATION AUTOMATIQUE RÉUSSIE - Structure Basée Domaines ║
║ ║
║ De: /api/v1, /api/v2, /api/v3 (confus) ║
║ Vers: /api/skydive, /api/cms, /api/herowars (clair) ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════╝
📊 STATISTIQUES DE LA MIGRATION
═══════════════════════════════════════════════════════════════════════════════
✓ Fichiers de routes migrés: 19 fichiers
✓ Domaines créés: 3 nouveaux domaines
✓ Fichiers index.js: 4 créés/mis à jour
✓ Documentation: 5 fichiers de rapport
✓ Scripts de migration: 3 scripts npm
✓ Commits Git: 2 commits
✓ Fichiers Swagger mis à jour: 4 fichiers YAML
🎯 STRUCTURE NOUVELLE CRÉÉE
═══════════════════════════════════════════════════════════════════════════════
src/routes/api/
├── skydive/ ← Parachutisme
│ ├── aeronefs.js
│ ├── applications.js
│ ├── canopies.js
│ ├── dropzones.js
│ ├── jumps.js
│ ├── pages.js
│ ├── profiles.js
│ ├── qcm.js
│ └── index.js
├── cms/ ← Gestion de contenu
│ ├── articles.routes.js
│ ├── comments.routes.js
│ ├── product.routes.js
│ ├── products.routes.js
│ ├── profiles.routes.js
│ ├── tags.routes.js
│ ├── user.routes.js
│ └── index.js
└── herowars/ ← Jeu HeroWars
├── clans.routes.js
├── members.routes.js
├── herowars.routes.js
└── index.js
📝 FICHIERS DE DOCUMENTATION CRÉÉS
═══════════════════════════════════════════════════════════════════════════════
1. MIGRATION_REPORT.md
└─ Rapport détaillé: structure ancienne → nouvelle, fichiers migrés
2. MIGRATION_COMPLETE_SUMMARY.md
└─ Résumé exécutif avec instructions de test et frontend
3. POST_MIGRATION_CHECKLIST.md
└─ Liste de vérification manuelle pour validation
4. SCRIPTS_MIGRATION_GUIDE.md
└─ Guide complet d'utilisation des scripts (CE FICHIER)
5. MIGRATION_SWAGGER_TODO.md
└─ Notes sur les mises à jour Swagger/OpenAPI
⚙️ SCRIPTS DE MIGRATION CRÉÉS
═══════════════════════════════════════════════════════════════════════════════
1. scripts/migrate-to-domain-structure.js
├─ Phase 1: Crée les répertoires de domaines
├─ Phase 2: Migre tous les fichiers de routes
├─ Phase 3: Génère les fichiers index.js
├─ Phase 4: Met à jour src/routes/api/index.js
├─ Phase 5: Crée les notes Swagger
├─ Phase 6: Gère les fichiers Swagger
├─ Phase 7: Effectue les opérations Git
├─ Phase 8: Valide la migration
└─ Phase 9: Génère un rapport
[✅ EXÉCUTÉ: commit 9f73ed0]
2. scripts/update-references-post-migration.js
├─ Phase 1: Met à jour les fichiers YAML Swagger
├─ Phase 2: Met à jour la collection/env Postman
├─ Phase 3: Scanne les références v1/v2/v3 restantes
└─ Phase 4: Génère une liste de vérification
[✅ EXÉCUTÉ]
3. scripts/finalize-migration.js
├─ Phase 1: Valide la structure des domaines
├─ Phase 2: Liste les anciens répertoires
├─ Phase 3: Optionnel - Nettoie les v1/v2/v3 (--cleanup)
├─ Phase 4: Optionnel - Teste les endpoints (--test)
└─ Phase 5: Génère un résumé final
[PRÊT À EXÉCUTER - voir instructions ci-dessous]
🚀 PROCHAINES ÉTAPES IMMÉDIATES
═══════════════════════════════════════════════════════════════════════════════
ÉTAPE 1️⃣: VALIDER LA STRUCTURE
────────────────────────────────────────────────────────────────────────────────
$ node scripts/finalize-migration.js
✓ Affichera: "skydive/: ✓ (8 route files)"
✓ Affichera: "cms/: ✓ (7 route files)"
✓ Affichera: "herowars/: ✓ (3 route files)"
ÉTAPE 2️⃣: NETTOYER LES ANCIENS RÉPERTOIRES (OPTIONNEL)
────────────────────────────────────────────────────────────────────────────────
OPTION A - Via script:
$ node scripts/finalize-migration.js --cleanup
OPTION B - Manuellement:
$ rm -rf src/routes/api/v1 src/routes/api/v2 src/routes/api/v3
$ git add -A && git commit -m "chore: remove old v1/v2/v3 directories"
ÉTAPE 3️⃣: TESTER LE SERVEUR
────────────────────────────────────────────────────────────────────────────────
Terminal 1 - Démarrer l'API:
$ npm run local
Terminal 2 - Tester les endpoints:
$ curl http://localhost:3200/api-docs # Swagger UI
$ curl http://localhost:3200/api/skydive/jumps # Skydive
$ curl http://localhost:3200/api/cms/articles # CMS
$ curl http://localhost:3200/api/herowars/clans # HeroWars
ÉTAPE 4️⃣: METTRE À JOUR LE FRONTEND (IMPORTANT!) 🔴
────────────────────────────────────────────────────────────────────────────────
A. Mettre à jour les environnements Angular:
Fichiers à modifier:
- src/environments/environment.ts
- src/environments/environment.development.ts
- src/environments/environment.local.ts
AVANT:
export const environment = {
apiUrl: '/api/v1',
cmsUrl: '/api/v2',
herowarsUrl: '/api/v3',
};
APRÈS:
export const environment = {
apiUrl: '/api/skydive',
cmsUrl: '/api/cms',
herowarsUrl: '/api/herowars',
};
B. Mettre à jour les services Angular:
Cherchez et remplacez les chemins en dur:
sed -i '' "s|'/api/v1/|'/api/skydive/|g" src/**/*.ts
sed -i '' "s|'/api/v2/|'/api/cms/|g" src/**/*.ts
sed -i '' "s|'/api/v3/|'/api/herowars/|g" src/**/*.ts
C. Tester le frontend:
$ npm start
Vérifier dans DevTools que les appels API vont vers /api/skydive/*, /api/cms/*, etc.
ÉTAPE 5️⃣: POUSSER LES CHANGEMENTS
────────────────────────────────────────────────────────────────────────────────
$ git push origin develop
ou
$ git push --all --follow-tags
📋 RÉSUMÉ DES COMMITS GIT
═══════════════════════════════════════════════════════════════════════════════
Commit 1: 9f73ed0
├─ Message: "refactor: restructure API routes from v1/v2/v3 to domain-based..."
├─ Actions:
│ ├─ Créé: src/routes/api/skydive/, cms/, herowars/
│ ├─ Copié: 19 fichiers de routes
│ └─ Mis à jour: src/routes/api/index.js
└─ État: ✅ MERGED
Commit 2: 74df96c
├─ Message: "docs: add migration documentation, finalization scripts, and update Swagger paths"
├─ Actions:
│ ├─ Créé: 4 fichiers de documentation
│ ├─ Créé: 2 scripts de finalisation
│ └─ Mis à jour: 4 fichiers Swagger YAML
└─ État: ✅ CURRENT HEAD
🔄 AVANT/APRÈS - COMPARAISON DES API
═══════════════════════════════════════════════════════════════════════════════
SAUT/PARACHUTISME:
AVANT: GET /api/v1/jumps
APRÈS: GET /api/skydive/jumps
──────────────────────
GET /api/v1/aeronefs → GET /api/skydive/aeronefs
POST /api/v1/aeronefs → POST /api/skydive/aeronefs
CONTENU:
AVANT: GET /api/v2/articles
APRÈS: GET /api/cms/articles
────────────────────────
GET /api/v2/articles/123 → GET /api/cms/articles/123
POST /api/v2/articles → POST /api/cms/articles
GET /api/v2/comments → GET /api/cms/comments
JEU:
AVANT: GET /api/v3/clans
APRÈS: GET /api/herowars/clans
────────────────────────
GET /api/v3/members → GET /api/herowars/members
POST /api/v3/members/123 → POST /api/herowars/members/123
⚠️ IMPORTANT: ROLLBACK EN CAS DE PROBLÈME
═══════════════════════════════════════════════════════════════════════════════
Si vous rencontrez des problèmes:
Option 1 - Peu de changements (rollback 2 commits):
$ git reset --hard HEAD~2
Option 2 - Si vous avez poussé, utiliser revert:
$ git revert 74df96c
$ git revert 9f73ed0
Option 3 - Restaurer depuis le remote:
$ git fetch origin
$ git reset --hard origin/develop
✅ CHECKLIST DE VALIDATION POST-MIGRATION
═══════════════════════════════════════════════════════════════════════════════
Backend (adastra_api):
☐ npm run local - serveur démarre sans erreur
☐ curl http://localhost:3200/api-docs - Swagger UI accessible
☐ Endpoints skydive fonctionnent: GET /api/skydive/jumps
☐ Endpoints CMS fonctionnent: GET /api/cms/articles
☐ Endpoints HeroWars fonctionnent: GET /api/herowars/clans
Frontend (adastra_app):
☐ npm start - app démarre sans erreur
☐ Appels API vont vers les nouveaux chemins
☐ Authentification toujours fonctionnelle
☐ Pages affichent les données correctement
☐ Aucune erreur 404 sur les endpoints
Git:
☐ Commits créés et visibles: git log --oneline -5
☐ Prêt pour: git push origin develop
Documentation:
☐ README.md mis à jour (optionnel)
☐ Équipe notifiée du changement
☐ Documentation technique mise à jour
📚 RESSOURCES SUPPLÉMENTAIRES
═══════════════════════════════════════════════════════════════════════════════
Consultez ces fichiers pour plus d'informations:
1. SCRIPTS_MIGRATION_GUIDE.md
└─ Guide détaillé de chaque script et options
2. POST_MIGRATION_CHECKLIST.md
└─ Liste complète de vérification manuelle
3. MIGRATION_COMPLETE_SUMMARY.md
└─ Résumé exécutif avec instructions
4. docs/*.md (depuis l'audit architectural)
└─ Architecture complète et ADRs
🎓 POINTS CLÉS À RETENIR
═══════════════════════════════════════════════════════════════════════════════
✓ NON-DESTRUCTIF: Les anciens répertoires restent, vous pouvez les nettoyer
progressivement après vérification
✓ AUTOMATISÉ: Scripts Python/Node qui gèrent la plupart des tâches
Swagger, Postman, routes mis à jour automatiquement
⚠️ MANUEL: Frontend DOIT être mis à jour (recherche/remplace)
Tests doivent être revérifiés
Documentation peut nécessiter mise à jour
✓ GIT-SAFE: Chaque étape crée un commit
Rollback facile si problème
Toutes les modifications sont tracées
✓ BÉNÉFICES: Chemins d'API clairs et explicites
Séparation nette des domaines métier
Meilleure architecture et maintenabilité
Préparation pour futures versions d'API
═══════════════════════════════════════════════════════════════════════════════
✨ Migration complétée avec succès! ✨
Prêt à continuer avec les 20 ADRs d'architecture?
(QUICK_START_WEEK1.md pour la Phase 1)
═══════════════════════════════════════════════════════════════════════════════
Date: 24 avril 2026
Statut: ✅ COMPLETE
Prochaine étape: Mise à jour du frontend + tests
+111
View File
@@ -0,0 +1,111 @@
╔════════════════════════════════════════════════════════════════════════════╗
║ MIGRATION SUCCESSFULLY COMPLETED ║
╚════════════════════════════════════════════════════════════════════════════╝
NEW API STRUCTURE:
├── /api/skydive/* ← Skydiving features (jumps, aeronefs, dropzones, etc.)
├── /api/cms/* ← Content management (articles, tags, comments, etc.)
└── /api/herowars/* ← Game features (clans, members, raids, etc.)
WHAT WAS CHANGED:
✓ Routes directory: v1/v2/v3 → domain-based structure
✓ Route definitions: Updated all index.js files
✓ Swagger YAML: Updated path prefixes to new domains
✓ Postman collection: Updated endpoint URLs
FILES MIGRATED:
✓ Skydive domain (8 route files):
- aeronefs.js, applications.js, canopies.js, dropzones.js
- jumps.js, pages.js, profiles.js, qcm.js
✓ CMS domain (8 route files):
- articles.routes.js, comments.routes.js, product.routes.js
- products.routes.js, profiles.routes.js, tags.routes.js, user.routes.js
✓ Hero Wars domain (3 route files):
- clans.routes.js, members.routes.js, herowars.routes.js
TESTING INSTRUCTIONS:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Start the API server:
npm run local
2. In another terminal, verify Swagger is updated:
curl http://localhost:3200/api-docs
3. Test a sample endpoint:
curl http://localhost:3200/api/skydive/jumps
curl http://localhost:3200/api/cms/articles
curl http://localhost:3200/api/herowars/clans
FRONTEND UPDATES REQUIRED:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
In your Angular frontend (adastra_app):
1. Update environment files:
src/environments/environment.ts
src/environments/environment.development.ts
src/environments/environment.local.ts
Replace:
- apiUrl: '/api/v1' → apiUrl: '/api/skydive'
- cmUrl: '/api/v2' → cmUrl: '/api/cms'
- hwUrl: '/api/v3' → hwUrl: '/api/herowars'
2. Update API service calls:
// Before:
http.get('/api/v1/jumps')
http.get('/api/v2/articles')
http.get('/api/v3/clans')
// After:
http.get('/api/skydive/jumps')
http.get('/api/cms/articles')
http.get('/api/herowars/clans')
3. Search & replace in your services:
sed -i 's|/api/v1/|/api/skydive/|g' src/**/*.ts
sed -i 's|/api/v2/|/api/cms/|g' src/**/*.ts
sed -i 's|/api/v3/|/api/herowars/|g' src/**/*.ts
GIT OPERATIONS:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
View migration commits:
git log --oneline -5
If needed, view detailed changes:
git show HEAD
Push to remote:
git push origin develop
ROLLBACK (if issues):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
If you need to rollback:
git reset --hard HEAD~2
(Adjust the number of commits based on history)
ADDITIONAL RESOURCES:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Documentation files created:
- MIGRATION_REPORT.md: Detailed migration information
- MIGRATION_SWAGGER_TODO.md: Swagger update notes
- POST_MIGRATION_CHECKLIST.md: Verification checklist
Scripts created:
- scripts/migrate-to-domain-structure.js: Main migration script
- scripts/update-references-post-migration.js: Post-migration updates
- scripts/finalize-migration.js: Cleanup and testing
═════════════════════════════════════════════════════════════════════════════
✓ Migration is complete! Follow the testing instructions above.
═════════════════════════════════════════════════════════════════════════════
+67
View File
@@ -0,0 +1,67 @@
═══════════════════════════════════════════════════════════════════════════════
API STRUCTURE MIGRATION REPORT
═══════════════════════════════════════════════════════════════════════════════
MIGRATION: v1/v2/v3 → Domain-Based (skydive/cms/herowars)
OLD STRUCTURE:
└── routes/api/
├── v1/ (Skydive routes)
├── v2/ (CMS + misc routes)
└── v3/ (Hero Wars routes)
NEW STRUCTURE:
└── routes/api/
├── skydive/
├── cms/
└── herowars/
ROUTE MAPPINGS:
✓ /api/v1/* → /api/skydive/*
- applications, aeronefs, canopies, dropzones, jumps, pages, profiles, qcm
✓ /api/v2/* → /api/cms/*
- user, articles, comments, product, products, profiles, tags
✓ /api/v3/* → /api/herowars/*
- clans, members, herowars (moved from v2)
FILES CREATED/UPDATED:
✓ src/routes/api/skydive/index.js
✓ src/routes/api/cms/index.js
✓ src/routes/api/herowars/index.js
✓ src/routes/api/index.js
✓ All route files copied to appropriate domains
MANUAL STEPS REQUIRED:
1. Update Swagger/OpenAPI documentation:
- Review MIGRATION_SWAGGER_TODO.md
- Update path prefixes in src/swagger/*.yaml files
- Update paths in src/config/swagger.js if needed
2. Update app.js (if direct version references exist):
- Search for 'v1', 'v2', 'v3' strings
- Replace with domain names where appropriate
3. Update tests and client calls:
- Replace /api/v1/ with /api/skydive/
- Replace /api/v2/ with /api/cms/
- Replace /api/v3/ with /api/herowars/
4. Update any documentation:
- README.md API endpoints section
- API documentation and guides
5. Test all endpoints:
- Verify each domain routes work correctly
- Check authentication/authorization still functions
- Validate error handling
OPTIONAL: Old v1/v2/v3 directories can be removed after verification:
rm -rf src/routes/api/v1
rm -rf src/routes/api/v2
rm -rf src/routes/api/v3
═══════════════════════════════════════════════════════════════════════════════
+19
View File
@@ -0,0 +1,19 @@
# Swagger Path Updates Required
The following Swagger YAML files need path updates:
## skydive.yaml
- Change: /api/v1/ → /api/skydive/
- Affected routes: /jumps, /aeronefs, /dropzones, /canopies, /pages, /qcm, /applications
## cms.yaml
- Change: /api/v2/ → /api/cms/
- Affected routes: /articles, /comments, /products, /tags, /profiles, /user
## herowars.yaml
- Change: /api/v3/ → /api/herowars/
- Affected routes: /clans, /members
- Note: Add herowars endpoint from former /api/v2/herowars
Update in: src/config/swagger.js if paths are hardcoded.
+80
View File
@@ -0,0 +1,80 @@
# Post-Migration Update Checklist
## Files Updated by Script ✓
- [x] Swagger YAML files (/api/v1 → /api/skydive, etc.)
- [x] Postman collection and environment files
- [x] API routes structure (new domains created)
## Manual Verification Required
### 1. Test API Endpoints
```bash
npm run local # Start the server
# In another terminal:
curl http://localhost:3200/api-docs # Check Swagger UI
```
### 2. Verify Routes
- [ ] GET /api/skydive/jumps
- [ ] GET /api/cms/articles
- [ ] GET /api/herowars/clans
- [ ] Other domain-specific endpoints
### 3. Frontend Updates Required (if applicable)
- [ ] Update Angular environment files (environment.ts, environment.development.ts, etc.)
- [ ] Replace all API calls from /api/v1, /api/v2, /api/v3 to new domains
- [ ] Update service layer URLs
- [ ] Update HTTP interceptors if needed
### 4. Documentation Updates
- [ ] Update README.md with new API structure
- [ ] Update API documentation (if any)
- [ ] Update deployment/infrastructure docs
- [ ] Update team wiki/documentation
### 5. CI/CD Pipeline (if applicable)
- [ ] Update build/deployment scripts referencing v1/v2/v3
- [ ] Update any health checks pointing to old paths
- [ ] Update monitoring/alerting rules
### 6. Client Applications
- [ ] Update all client libraries/SDKs
- [ ] Update mobile app API endpoints
- [ ] Update third-party integrations
### 7. Database/Caching (if applicable)
- [ ] Clear any cached references to old endpoints
- [ ] Update API documentation in databases
- [ ] Check for hardcoded URLs in configuration
## Git Operations
```bash
# View the migration commits
git log --oneline -5
# If rollback needed:
git revert <commit-hash>
# Push changes
git push origin develop
```
## Optional: Cleanup Old Directories
```bash
# After thorough testing, remove old v1/v2/v3 directories:
rm -rf src/routes/api/v1
rm -rf src/routes/api/v2
rm -rf src/routes/api/v3
git add -A
git commit -m "chore: remove old v1/v2/v3 route directories"
```
## Rollback Procedure
If issues arise, rollback with:
```bash
git reset --hard HEAD~2 # Adjust commit count if needed
```
---
Document generated: 2026-04-23T22:48:52.497Z
+329
View File
@@ -0,0 +1,329 @@
# Migration Scripts - Guide d'utilisation
## Vue d'ensemble
Cette migration restructure votre API Express de `/api/v1` `/api/v2` `/api/v3` (qui représentaient des domaines métier, pas des versions API) vers une architecture basée sur les domaines avec des chemins clairs et explicites.
### Ancien structure (confuse)
```
/api/v1/* → Skydive features
/api/v2/* → CMS features
/api/v3/* → Hero Wars features
```
### Nouvelle structure (claire)
```
/api/skydive/* ← Toutes les fonctionnalités de parachutisme
/api/cms/* ← Gestion de contenu (articles, tags, etc.)
/api/herowars/* ← Gestion du jeu HeroWars (clans, membres, raids)
```
---
## Scripts de migration
### 1. `migrate-to-domain-structure.js` ✓ EXÉCUTÉ
**Rôle:** Crée la nouvelle structure et migre les fichiers
**Statut:** ✅ Completed
- Créé les répertoires `/api/skydive`, `/api/cms`, `/api/herowars`
- Copié tous les fichiers de routes vers les nouveaux emplacements
- Généré les nouveaux fichiers `index.js` pour chaque domaine
- Mis à jour `src/routes/api/index.js` pour utiliser les nouveaux chemins
- Créé un commit Git
**Fichiers modifiés:**
```
✓ src/routes/api/skydive/ (8 fichiers)
✓ src/routes/api/cms/ (8 fichiers)
✓ src/routes/api/herowars/ (3 fichiers)
✓ src/routes/api/index.js (mis à jour)
```
**Rapports générés:**
- `MIGRATION_REPORT.md` - Détails complets de la migration
- `MIGRATION_SWAGGER_TODO.md` - Tâches pour Swagger
---
### 2. `update-references-post-migration.js` ✓ EXÉCUTÉ
**Rôle:** Met à jour les références aux chemins dans la documentation
**Statut:** ✅ Completed
- Mis à jour les fichiers YAML Swagger (`/api/v1/``/api/skydive/`, etc.)
- Mis à jour la collection et l'environnement Postman
- Scanné les fichiers clés pour les références restantes
**Rapports générés:**
- `POST_MIGRATION_CHECKLIST.md` - Liste de vérification manuelle
---
### 3. `finalize-migration.js`
**Rôle:** Valide, nettoie, et teste la migration
**Options disponibles:**
```bash
# Valider la structure sans rien faire
node scripts/finalize-migration.js
# Valider et nettoyer les anciens répertoires
node scripts/finalize-migration.js --cleanup
# Valider et tester les endpoints (nécessite le serveur en cours d'exécution)
node scripts/finalize-migration.js --test
# Mode complet: validation, nettoyage et résumé
node scripts/finalize-migration.js --full
```
**Statut:** ✅ Ready to run
**Rapport généré:**
- `MIGRATION_COMPLETE_SUMMARY.md` - Résumé final avec instructions
---
## Guide étape par étape
### Étape 1: Vérifier la migration ✅
```bash
ls -la src/routes/api/
# Devrait afficher: cms/, herowars/, skydive/, v1/, v2/, v3/, index.js
```
### Étape 2: Valider la structure
```bash
node scripts/finalize-migration.js
```
**Résultat attendu:**
```
✓ skydive/: ✓ (8 route files)
✓ cms/: ✓ (7 route files)
✓ herowars/: ✓ (3 route files)
```
### Étape 3: Nettoyer les anciens répertoires (OPTIONNEL)
```bash
# Option A: Via le script
node scripts/finalize-migration.js --cleanup
# Option B: Manuellement
rm -rf src/routes/api/v1 src/routes/api/v2 src/routes/api/v3
git add -A
git commit -m "chore: remove old v1/v2/v3 route directories"
```
### Étape 4: Mettre à jour le frontend (IMPORTANT)
**Fichiers à modifier dans `adastra_app/src/environments/`:**
#### `environment.ts`
```typescript
// AVANT:
export const environment = {
production: false,
apiUrl: '/api/v1',
cmsUrl: '/api/v2',
herowarsUrl: '/api/v3',
};
// APRÈS:
export const environment = {
production: false,
apiUrl: '/api/skydive',
cmsUrl: '/api/cms',
herowarsUrl: '/api/herowars',
};
```
#### `environment.development.ts` et `environment.local.ts`
Applique les mêmes changements
**Mise à jour des services Angular:**
```typescript
// Dans vos services (par exemple, src/app/services/*.service.ts)
// AVANT:
this.http.get(environment.apiUrl + '/jumps')
this.http.get(environment.cmsUrl + '/articles')
this.http.get(environment.herowarsUrl + '/clans')
// APRÈS:
this.http.get(environment.apiUrl + '/jumps')
this.http.get(environment.cmsUrl + '/articles')
this.http.get(environment.herowarsUrl + '/clans')
// Pas de changement si vous utilisez les variables d'environnement!
// Sinon, cherchez/remplacez les chemins en dur
```
**Automatiser la mise à jour du frontend (macOS/Linux):**
```bash
cd adastra_app
sed -i '' "s|/api/v1|/api/skydive|g" src/**/*.ts
sed -i '' "s|/api/v2|/api/cms|g" src/**/*.ts
sed -i '' "s|/api/v3|/api/herowars|g" src/**/*.ts
```
### Étape 5: Tester les endpoints
**Démarrer le serveur API:**
```bash
cd adastra_api
npm run local
```
**Dans un autre terminal, tester les nouveaux chemins:**
```bash
# Tester Swagger UI
curl http://localhost:3200/api-docs
# Tester les endpoints des domaines
curl http://localhost:3200/api/skydive/jumps
curl http://localhost:3200/api/cms/articles
curl http://localhost:3200/api/herowars/clans
# Avec authentification si nécessaire
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3200/api/skydive/jumps
```
### Étape 6: Tester le frontend
```bash
cd adastra_app
npm start
# Ou avec configuration spécifique
npm run local # ng serve --configuration local
```
Vérifier dans les DevTools que les appels API vont vers les nouveaux chemins.
---
## Statistiques de la migration
| Métrique | Valeur |
|----------|--------|
| Nouveaux domaines créés | 3 (skydive, cms, herowars) |
| Fichiers de routes migrés | 19 |
| Fichiers index.js créés/mis à jour | 4 |
| Fichiers Swagger mis à jour | Oui |
| Fichiers Postman mis à jour | Oui |
| Commits Git créés | 1 (structure) + opt. 1 (nettoyage) |
---
## Fichiers de rapport créés
| Fichier | Contenu |
|---------|---------|
| `MIGRATION_REPORT.md` | Rapport détaillé de la migration |
| `MIGRATION_SWAGGER_TODO.md` | Notes pour les mises à jour Swagger |
| `POST_MIGRATION_CHECKLIST.md` | Liste de vérification manuelle |
| `MIGRATION_COMPLETE_SUMMARY.md` | Résumé final et instructions |
| `SCRIPTS_MIGRATION_GUIDE.md` | Ce fichier |
---
## Procédure de rollback
Si vous devez annuler la migration:
```bash
# Voir l'historique
git log --oneline -10
# Annuler les changements (ajuster le nombre de commits)
git reset --hard HEAD~2
# Ou restaurer une branche spécifique
git reset --hard origin/develop
```
---
## Points clés à retenir
**La migration est non-destructive:**
- Les anciens répertoires v1/v2/v3 existent toujours
- Vous pouvez les supprimer après vérification
**Mises à jour automatisées:**
- Scripts: Oui ✓
- Swagger: Oui ✓
- Postman: Oui ✓
⚠️ **Mises à jour manuelles requises:**
- Frontend Angular (environnement + services)
- Tous les appels API en dur dans le code cliente
- Documentation externe
- Tests d'intégration
**Git-safe:**
- Chaque étape crée un commit
- Rollback facile si problème
---
## Troubleshooting
### Les endpoints retournent 404
- ✓ Vérifier que le serveur a redémarré après la migration
- ✓ Vérifier les chemins dans Swagger UI (http://localhost:3200/api-docs)
- ✓ Vérifier que le backend a bien recompilé (avec nodemon)
### Les routes ne sont pas trouvées
- ✓ Vérifier que `src/routes/api/index.js` a les bonnes références
- ✓ Vérifier que chaque domaine a un `index.js`
- ✓ Vérifier l'ordre des middlewares dans `app.js`
### Erreurs d'authentification
- ✓ Les middlewares d'auth ne sont pas affectés
- ✓ Les tokens JWT restent valides
- ✓ Les headers restent les mêmes
### Le frontend ne peut pas accéder à l'API
- ✓ Vérifier CORS dans `app.js`
- ✓ Vérifier les URLs dans les environnements Angular
- ✓ Vérifier les appels http dans les services
---
## Prochaines étapes
1. ✅ Tester tous les endpoints du backend
2. ✅ Mettre à jour le frontend (environnement + services)
3. ✅ Tester le frontend avec le backend modifié
4. ✅ Mettre à jour la documentation
5. ✅ Nettoyer les anciens répertoires v1/v2/v3 (optionnel)
6. ✅ Déployer en staging/production
---
## Ressources supplémentaires
- Documentation architecture: `ARCHITECTURE_DIAGRAMS.md`
- ADR (Architecture Decision Records): `ADR_INDEX.md`
- Configuration Swagger: `src/config/swagger.js`
- Routes configuration: `src/routes/api/index.js`
---
## Support
Pour des questions ou problèmes:
1. ✓ Consulter los fichiers de rapport (`POST_MIGRATION_CHECKLIST.md`, etc.)
2. ✓ Vérifier les logs du serveur: `npm run local` (output)
3. ✓ Vérifier Swagger UI: http://localhost:3200/api-docs
4. ✓ Exécuter la validation: `node scripts/finalize-migration.js`
---
**Migration effectuée le:** 24 avril 2026
**Version API:** v1/v2/v3 → domain-based
**Status:** ✅ Complete
+762
View File
@@ -0,0 +1,762 @@
# Méthodes disponibles sur les modèles MySQL (Sequelize)
Ce document liste toutes les méthodes automatiquement générées par Sequelize pour chaque modèle en fonction des associations définies dans `src/database/relationships/index.js`.
---
## Table des matières
1. [Article](#article)
2. [Tag](#tag)
3. [User](#user)
4. [Comment](#comment)
5. [Favorite](#favorite)
6. [Follower](#follower)
7. [Product](#product)
8. [Brand](#brand)
9. [Category](#category)
10. [Packaging](#packaging)
11. [TagList](#taglist)
12. [Role](#role)
13. [UserRoleXref](#userroleexref)
14. [ProductCategoryXref](#productcategoryxref)
15. [ProductTagXref](#producttagxref)
---
## Article
### Many-to-Many (belongsToMany)
#### Tags via `TagList`
Alias: `articleTags`
```javascript
article.getArticleTags() // Récupère tous les tags
article.setArticleTags([...]) // Définit les tags
article.addArticleTag(tag) // Ajoute un tag
article.removeArticleTag(tag) // Retire un tag
article.countArticleTags() // Compte les tags
article.hasArticleTag(tag) // Vérifie si le tag est lié
```
#### Users (Favoris) via `Favorite`
Alias: `articleFavoriteUsers` (cascade delete activé)
```javascript
article.getArticleFavoriteUsers() // Récupère les utilisateurs qui ont favorisé
article.setArticleFavoriteUsers([...]) // Définit les utilisateurs
article.addArticleFavoriteUser(user) // Ajoute un utilisateur
article.removeArticleFavoriteUser(user) // Retire un utilisateur
article.countArticleFavoriteUsers() // Compte les utilisateurs
article.hasArticleFavoriteUser(user) // Vérifie si l'utilisateur a favorisé
```
### One-to-Many (hasMany)
#### Comments (cascade delete activé)
```javascript
article.getComments() // Récupère tous les commentaires
article.setComments([...]) // Définit les commentaires
article.addComment(comment) // Ajoute un commentaire
article.removeComment(comment) // Retire un commentaire
article.countComments() // Compte les commentaires
article.hasComment(comment) // Vérifie si le commentaire existe
article.createComment({...}) // Crée un commentaire
```
#### Favorites (cascade delete activé)
```javascript
article.getFavorites() // Récupère les enregistrements Favorite
article.setFavorites([...]) // Définit les favoris
article.addFavorite(favorite) // Ajoute un Favorite
article.removeFavorite(favorite) // Retire un Favorite
article.countFavorites() // Compte les Favorites
article.hasFavorite(favorite) // Vérifie si le Favorite existe
article.createFavorite({...}) // Crée un Favorite
```
#### TagLists (cascade delete activé)
```javascript
article.getTagLists() // Récupère les enregistrements TagList
article.setTagLists([...]) // Définit les TagLists
article.addTagList(tagList) // Ajoute un TagList
article.removeTagList(tagList) // Retire un TagList
article.countTagLists() // Compte les TagLists
article.hasTagList(tagList) // Vérifie si le TagList existe
article.createTagList({...}) // Crée un TagList
```
### Belongs-To
#### Author (User)
```javascript
article.getAuthor() // Récupère l'auteur
article.setAuthor(user) // Définit l'auteur
article.createAuthor({...}) // Crée un auteur
```
### Instance Methods
```javascript
article.toJSONFor() // Formate en JSON
```
---
## Tag
### Many-to-Many (belongsToMany)
#### Articles via `TagList`
Alias: `articleIdArticleTagLists`
```javascript
tag.getArticleIdArticleTagLists() // Récupère les articles
tag.setArticleIdArticleTagLists([...])
tag.addArticleIdArticleTagList(article)
tag.removeArticleIdArticleTagList(article)
tag.countArticleIdArticleTagLists()
tag.hasArticleIdArticleTagList(article)
```
#### Products via `ProductTagXref`
Alias: `productIdProductProductTagXrefs`
```javascript
tag.getProductIdProductProductTagXrefs()
tag.setProductIdProductProductTagXrefs([...])
tag.addProductIdProductProductTagXref(product)
tag.removeProductIdProductProductTagXref(product)
tag.countProductIdProductProductTagXrefs()
tag.hasProductIdProductProductTagXref(product)
```
### One-to-Many (hasMany)
#### TagLists
```javascript
tag.getTagLists() // Récupère les enregistrements TagList
tag.setTagLists([...])
tag.addTagList(tagList)
tag.removeTagList(tagList)
tag.countTagLists()
tag.hasTagList(tagList)
tag.createTagList({...})
```
#### ProductTagXrefs
```javascript
tag.getProductTagXrefs() // Récupère les ProductTagXrefs
tag.setProductTagXrefs([...])
tag.addProductTagXref(xref)
tag.removeProductTagXref(xref)
tag.countProductTagXrefs()
tag.hasProductTagXref(xref)
tag.createProductTagXref({...})
```
### Instance Methods
```javascript
tag.toJSONFor() // Formate en JSON
```
---
## User
### Many-to-Many (belongsToMany)
#### Articles (Favoris) via `Favorite`
Alias: `articleIdArticles`
```javascript
user.getArticleIdArticles() // Récupère les articles favorisés
user.setArticleIdArticles([...])
user.addArticleIdArticle(article)
user.removeArticleIdArticle(article)
user.countArticleIdArticles()
user.hasArticleIdArticle(article)
```
#### Followers (ceux qui vous suivent) via `Follower`
Alias: `followerIdUsers`
```javascript
user.getFollowerIdUsers() // Récupère les followers
user.setFollowerIdUsers([...])
user.addFollowerIdUser(user)
user.removeFollowerIdUser(user)
user.countFollowerIdUsers()
user.hasFollowerIdUser(user)
```
#### Following (que vous suivez) via `Follower`
Alias: `userIdUserFollowers`
```javascript
user.getUserIdUserFollowers() // Récupère ceux que vous suivez
user.setUserIdUserFollowers([...])
user.addUserIdUserFollower(user)
user.removeUserIdUserFollower(user)
user.countUserIdUserFollowers()
user.hasUserIdUserFollower(user)
```
#### Roles via `UserRoleXref`
Alias: `roleIdRoles`
```javascript
user.getRoleIdRoles() // Récupère les rôles
user.setRoleIdRoles([...])
user.addRoleIdRole(role)
user.removeRoleIdRole(role)
user.countRoleIdRoles()
user.hasRoleIdRole(role)
```
### One-to-Many (hasMany)
#### Articles (créés par l'utilisateur)
```javascript
user.getArticles() // Récupère les articles créés
user.setArticles([...])
user.addArticle(article)
user.removeArticle(article)
user.countArticles()
user.hasArticle(article)
user.createArticle({...})
```
#### Comments (créés par l'utilisateur)
```javascript
user.getComments() // Récupère les commentaires créés
user.setComments([...])
user.addComment(comment)
user.removeComment(comment)
user.countComments()
user.hasComment(comment)
user.createComment({...})
```
#### Favorites (enregistrements)
```javascript
user.getFavorites() // Récupère les Favorites
user.setFavorites([...])
user.addFavorite(favorite)
user.removeFavorite(favorite)
user.countFavorites()
user.hasFavorite(favorite)
user.createFavorite({...})
```
#### Followers (enregistrements)
```javascript
user.getFollowers() // Récupère les Followers
user.setFollowers([...])
user.addFollower(follower)
user.removeFollower(follower)
user.countFollowers()
user.hasFollower(follower)
user.createFollower({...})
```
#### FollowerFollowers (ceux qui vous suivent via enregistrement)
```javascript
user.getFollowerFollowers() // Récupère les FollowerFollowers
user.setFollowerFollowers([...])
user.addFollowerFollower(follower)
user.removeFollowerFollower(follower)
user.countFollowerFollowers()
user.hasFollowerFollower(follower)
user.createFollowerFollower({...})
```
#### Products (créés/possédés)
```javascript
user.getProducts() // Récupère les produits
user.setProducts([...])
user.addProduct(product)
user.removeProduct(product)
user.countProducts()
user.hasProduct(product)
user.createProduct({...})
```
#### UserRoleXrefs
```javascript
user.getUserRoleXrefs() // Récupère les UserRoleXrefs
user.setUserRoleXrefs([...])
user.addUserRoleXref(xref)
user.removeUserRoleXref(xref)
user.countUserRoleXrefs()
user.hasUserRoleXref(xref)
user.createUserRoleXref({...})
```
### Instance Methods
```javascript
user.validPassword(password) // Valide le mot de passe
user.setPassword(password) // Définit le mot de passe (hash)
user.generateJWT() // Génère un JWT
user.toAuthJSON() // Retourne objet auth
user.toJSONFor() // Formate en JSON
user.toProfileJSONFor() // Formate profil en JSON
```
---
## Comment
### Belongs-To
#### Article
```javascript
comment.getArticle() // Récupère l'article
comment.setArticle(article) // Définit l'article
comment.createArticle({...}) // Crée un article
```
#### Author (User)
```javascript
comment.getAuthor() // Récupère l'auteur
comment.setAuthor(user) // Définit l'auteur
comment.createAuthor({...}) // Crée un auteur
```
### Instance Methods
```javascript
comment.toJSONFor() // Formate en JSON
```
---
## Favorite
### Belongs-To
#### User
```javascript
favorite.getUser() // Récupère l'utilisateur
favorite.setUser(user) // Définit l'utilisateur
favorite.createUser({...}) // Crée un utilisateur
```
#### Article
```javascript
favorite.getArticle() // Récupère l'article
favorite.setArticle(article) // Définit l'article
favorite.createArticle({...}) // Crée un article
```
### Instance Methods
```javascript
favorite.toJSONFor() // Formate en JSON
```
---
## Follower
### Belongs-To
#### User (l'utilisateur suivi)
```javascript
follower.getUser() // Récupère l'utilisateur suivi
follower.setUser(user) // Définit l'utilisateur suivi
follower.createUser({...}) // Crée un utilisateur
```
#### Follower (l'utilisateur qui suit) - alias 'follower'
```javascript
follower.getFollower() // Récupère celui qui suit
follower.setFollower(user) // Définit celui qui suit
follower.createFollower({...}) // Crée un utilisateur qui suit
```
### Instance Methods
```javascript
follower.toJSONFor() // Formate en JSON
```
---
## Product
### Many-to-Many (belongsToMany)
#### Categories via `ProductCategoryXref`
Alias: `productCategories`
```javascript
product.getProductCategories() // Récupère les catégories
product.setProductCategories([...])
product.addProductCategory(category)
product.removeProductCategory(category)
product.countProductCategories()
product.hasProductCategory(category)
```
#### Tags via `ProductTagXref`
Alias: `productTags`
```javascript
product.getProductTags() // Récupère les tags
product.setProductTags([...])
product.addProductTag(tag)
product.removeProductTag(tag)
product.countProductTags()
product.hasProductTag(tag)
```
### One-to-Many (hasMany)
#### ProductCategoryXrefs
```javascript
product.getProductCategoryXrefs() // Récupère les liens catégories
product.setProductCategoryXrefs([...])
product.addProductCategoryXref(xref)
product.removeProductCategoryXref(xref)
product.countProductCategoryXrefs()
product.hasProductCategoryXref(xref)
product.createProductCategoryXref({...})
```
#### ProductTagXrefs
```javascript
product.getProductTagXrefs() // Récupère les liens tags
product.setProductTagXrefs([...])
product.addProductTagXref(xref)
product.removeProductTagXref(xref)
product.countProductTagXrefs()
product.hasProductTagXref(xref)
product.createProductTagXref({...})
```
### Belongs-To
#### Brand
```javascript
product.getBrand() // Récupère la marque
product.setBrand(brand) // Définit la marque
product.createBrand({...}) // Crée une marque
```
#### Owner (User)
```javascript
product.getOwner() // Récupère le propriétaire
product.setOwner(user) // Définit le propriétaire
product.createOwner({...}) // Crée un propriétaire
```
#### Packaging
```javascript
product.getPackaging() // Récupère l'emballage
product.setPackaging(packaging) // Définit l'emballage
product.createPackaging({...}) // Crée un emballage
```
---
## Brand
### One-to-Many (hasMany)
#### Products
```javascript
brand.getProducts() // Récupère les produits
brand.setProducts([...])
brand.addProduct(product)
brand.removeProduct(product)
brand.countProducts()
brand.hasProduct(product)
brand.createProduct({...})
```
---
## Category
### Many-to-Many (belongsToMany)
#### Products via `ProductCategoryXref`
Alias: `productIdProducts`
```javascript
category.getProductIdProducts() // Récupère les produits
category.setProductIdProducts([...])
category.addProductIdProduct(product)
category.removeProductIdProduct(product)
category.countProductIdProducts()
category.hasProductIdProduct(product)
```
### One-to-Many (hasMany)
#### ProductCategoryXrefs
```javascript
category.getProductCategoryXrefs() // Récupère les liens produits
category.setProductCategoryXrefs([...])
category.addProductCategoryXref(xref)
category.removeProductCategoryXref(xref)
category.countProductCategoryXrefs()
category.hasProductCategoryXref(xref)
category.createProductCategoryXref({...})
```
---
## Packaging
### One-to-Many (hasMany)
#### Products
```javascript
packaging.getProducts() // Récupère les produits
packaging.setProducts([...])
packaging.addProduct(product)
packaging.removeProduct(product)
packaging.countProducts()
packaging.hasProduct(product)
packaging.createProduct({...})
```
---
## TagList
### Belongs-To
#### Article
```javascript
tagList.getArticle() // Récupère l'article
tagList.setArticle(article) // Définit l'article
tagList.createArticle({...}) // Crée un article
```
#### Tag
Alias: `tagNameTag`
```javascript
tagList.getTagNameTag() // Récupère le tag
tagList.setTagNameTag(tag) // Définit le tag
tagList.createTagNameTag({...}) // Crée un tag
```
---
## Role
### Many-to-Many (belongsToMany)
#### Users via `UserRoleXref`
Alias: `userIdUserUserRoleXrefs`
```javascript
role.getUserIdUserUserRoleXrefs() // Récupère les utilisateurs
role.setUserIdUserUserRoleXrefs([...])
role.addUserIdUserUserRoleXref(user)
role.removeUserIdUserUserRoleXref(user)
role.countUserIdUserUserRoleXrefs()
role.hasUserIdUserUserRoleXref(user)
```
### One-to-Many (hasMany)
#### UserRoleXrefs
```javascript
role.getUserRoleXrefs() // Récupère les UserRoleXrefs
role.setUserRoleXrefs([...])
role.addUserRoleXref(xref)
role.removeUserRoleXref(xref)
role.countUserRoleXrefs()
role.hasUserRoleXref(xref)
role.createUserRoleXref({...})
```
---
## UserRoleXref
### Belongs-To
#### User
```javascript
xref.getUser() // Récupère l'utilisateur
xref.setUser(user) // Définit l'utilisateur
xref.createUser({...}) // Crée un utilisateur
```
#### Role
```javascript
xref.getRole() // Récupère le rôle
xref.setRole(role) // Définit le rôle
xref.createRole({...}) // Crée un rôle
```
---
## ProductCategoryXref
### Belongs-To
#### Product
```javascript
xref.getProduct() // Récupère le produit
xref.setProduct(product) // Définit le produit
xref.createProduct({...}) // Crée un produit
```
#### Category
```javascript
xref.getCategory() // Récupère la catégorie
xref.setCategory(category) // Définit la catégorie
xref.createCategory({...}) // Crée une catégorie
```
---
## ProductTagXref
### Belongs-To
#### Product
```javascript
xref.getProduct() // Récupère le produit
xref.setProduct(product) // Définit le produit
xref.createProduct({...}) // Crée un produit
```
#### Tag
Alias: `tagNameTag`
```javascript
xref.getTagNameTag() // Récupère le tag
xref.setTagNameTag(tag) // Définit le tag
xref.createTagNameTag({...}) // Crée un tag
```
---
## Notes générales
1. **Paramètres `options`** : Presque toutes les méthodes `get*()` acceptent un objet `options` pour personnaliser la requête :
```javascript
model.getAssociated({
where: { createdAt: { [Op.gte]: someDate } },
limit: 10,
offset: 0,
order: [['createdAt', 'DESC']]
});
```
2. **Transactions** : Encapsulez les opérations dans une transaction :
```javascript
const transaction = await sequelize.transaction();
await model.addAssociated(associated, { transaction });
await transaction.commit();
```
3. **Eager Loading** : Utilisez `include` pour charger les associations :
```javascript
const article = await Article.findByPk(1, {
include: [
{ model: Tag, as: 'articleTags' },
{ model: User, as: 'author' },
{ model: Comment, as: 'comments' }
]
});
```
4. **Alias vs Nom généré** : Le nom des méthodes dépend de l'alias défini. Exemple :
- Alias `articleTags` → `getArticleTags()`, `addArticleTag()`
- Alias `tagLists` → `getTagLists()`, `addTagList()`
5. **Toutes les méthodes de manipulation** acceptent un paramètre `options` final :
```javascript
await article.addTagList(tag, { transaction, validate: true });
```
---
## Seeders
### Seeder Articles (20251127-add-articles.js)
Ce seeder ajoute automatiquement 3 articles avec du contenu Lorem Ipsum et les associe à des tags d'animaux.
#### Exécution
```bash
# Exécuter tous les seeders
npx sequelize-cli db:seed:all
# Annuler un seeder spécifique
npx sequelize-cli db:seed:undo --seed 20251127-add-articles.js
# Annuler tous les seeders
npx sequelize-cli db:seed:undo:all
```
#### Articles créés
| Titre | Tags | Slug |
|-------|------|------|
| Introduction aux écosystèmes marins | Dolphin, Eagle, Wolf | introduction-aux-ecosystemes-marins |
| Les prédateurs de la savane africaine | Lion, Tiger, Wolf | les-predateurs-de-la-savane-africaine |
| L'intelligence animale au-delà de nos attentes | Eagle, Dolphin, Lion | lintelligence-animale-au-dela-de-nos-attentes |
#### Tags disponibles
- Lion
- Eagle
- Dolphin
- Tiger
- Wolf
#### Fonctionnalités du seeder
- ✅ Crée automatiquement les 5 tags s'ils n'existent pas
- ✅ Génère des slugs uniques pour chaque article
- ✅ Associe 3 tags à chaque article via la table `tagList`
- ✅ Utilise les transactions pour l'intégrité des données
- ✅ Support du rollback via `db:seed:undo`
---
## Migrations et Schéma
### Migration initiale (20251127000000-initial-schema.js)
Crée tous les 15 tables avec les contraintes CASCADE appropriées :
**Tables avec CASCADE delete activé :**
- `article` → `comment` (foreignKey: `articleId`)
- `article` → `favorite` (foreignKey: `articleId`)
- `article` → `tagList` (foreignKey: `articleId`)
- `user` → `article` (foreignKey: `authorId`)
- `user` → `comment` (foreignKey: `authorId`)
- `tag` → `tagList` (foreignKey: `tagName`)
**Exécution**
```bash
# Appliquer les migrations
npx sequelize-cli db:migrate
# Voir le statut des migrations
npx sequelize-cli db:migrate:status
# Annuler les migrations
npx sequelize-cli db:migrate:undo:all
```
---
## Configuration de la base de données
### Variables d'environnement
Le fichier `.env.development` doit contenir :
```
DB_HOST=localhost
DB_USER=root
DB_PASS=password
DB_NAME=adastra
DB_DIALECT=mysql
```
### Validation du schéma au démarrage
L'application valide automatiquement la présence du schéma au démarrage :
- ✅ Si le schéma est absent, l'app échoue avec un message d'erreur
- ✅ Si le schéma est présent, les associations sont créées
- ✅ Message d'aide fourni pour exécuter les migrations manquantes
```bash
# Démarrer l'app (validera le schéma)
npm run local # Développement avec nodemon
npm run dev # Développement
npm start # Production
```
+210
View File
@@ -0,0 +1,210 @@
# Guide Swagger - Documentation OpenAPI pour Adastra API
## Accès à la documentation
Une fois le serveur lancé, accédez à : **http://localhost:3200/api-docs**
## Exemple de documentation pour une route
Voici un exemple de comment documenter une GET route avec des paramètres de query :
```javascript
/**
* @swagger
* /api/v1/articles:
* get:
* summary: Récupère la liste des articles
* description: Retourne une liste paginée de tous les articles
* tags:
* - Articles
* parameters:
* - in: query
* name: page
* schema:
* type: integer
* default: 1
* description: Numéro de page
* - in: query
* name: limit
* schema:
* type: integer
* default: 10
* description: Nombre d'articles par page
* responses:
* 200:
* description: Liste des articles récupérée avec succès
* content:
* application/json:
* schema:
* type: object
* properties:
* data:
* type: array
* items:
* type: object
* properties:
* id:
* type: integer
* title:
* type: string
* content:
* type: string
* total:
* type: integer
* 400:
* description: Erreur de validation
* 401:
* description: Non authentifié
* 500:
* description: Erreur serveur
*/
router.get('/', async (req, res) => {
// ... logique du contrôleur
});
```
## Exemple avec POST et authentification
```javascript
/**
* @swagger
* /api/v1/articles:
* post:
* summary: Crée un nouvel article
* description: Crée un nouvel article avec les données fournies
* tags:
* - Articles
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - title
* - content
* properties:
* title:
* type: string
* example: "Mon Article"
* content:
* type: string
* example: "Contenu de l'article"
* tags:
* type: array
* items:
* type: string
* example: ["tag1", "tag2"]
* responses:
* 201:
* description: Article créé avec succès
* content:
* application/json:
* schema:
* type: object
* properties:
* id:
* type: integer
* title:
* type: string
* content:
* type: string
* 400:
* description: Données invalides
* 401:
* description: Non authentifié
*/
router.post('/', authenticate, async (req, res) => {
// ... logique du contrôleur
});
```
## Exemple avec paramètres URL
```javascript
/**
* @swagger
* /api/v1/articles/{id}:
* get:
* summary: Récupère un article par ID
* tags:
* - Articles
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: ID de l'article
* responses:
* 200:
* description: Article récupéré avec succès
* 404:
* description: Article non trouvé
* 500:
* description: Erreur serveur
*/
router.get('/:id', async (req, res) => {
// ... logique du contrôleur
});
```
## Types de schémas courants
### Objets simples
```javascript
schema: {
type: object
properties:
id: { type: integer }
name: { type: string }
email: { type: string, format: email }
age: { type: integer, minimum: 0 }
isActive: { type: boolean }
}
```
### Arrays
```javascript
schema: {
type: array
items:
type: object
properties:
id: { type: integer }
name: { type: string }
}
```
### Enums
```javascript
schema: {
type: string
enum: ["pending", "approved", "rejected"]
}
```
## Tags disponibles
Les tags disponibles dans la config Swagger sont :
- **Articles** - Gestion des articles
- **Users** - Gestion des utilisateurs
- **Products** - Gestion des produits
- **Clans** - Gestion des clans
- **Hero Wars** - Données Hero Wars
## Instructions générales
1. **Placez les commentaires JSDoc directement au-dessus de la définition de la route**
2. **Utilisez le tag `@swagger`** pour indiquer que c'est de la documentation OpenAPI
3. **Commencez par le chemin d'accès** : `/api/v1/articles`, `/api/v1/articles/{id}`, etc.
4. **Spécifiez la méthode HTTP** : `get`, `post`, `put`, `delete`, `patch`
5. **Incluez toujours** : `summary`, `description`, `tags`, `responses`
6. **Pour les routes protégées**, utilisez `security: [{ bearerAuth: [] }]` ou `security: [{ apiKeyAuth: [] }]`
## Pour plus de détails
Consultez la documentation officielle : https://swagger.io/specification/
---
**Note** : Une fois que vous aurez ajouté les commentaires Swagger à vos routes, redémarrez le serveur et accédez à `/api-docs` pour voir la documentation mise à jour.