feat: ajout de claude + correction des tests
All checks were successful
Build and Deploy / deploy (push) Successful in 9m36s
All checks were successful
Build and Deploy / deploy (push) Successful in 9m36s
This commit is contained in:
parent
b5a832fbbc
commit
dae215dd3d
139
.claude/skills/hexagonal-arch/SKILL.md
Normal file
139
.claude/skills/hexagonal-arch/SKILL.md
Normal file
@@ -0,0 +1,139 @@
|
||||
---
|
||||
name: hexagonal-arch
|
||||
description: Architecture hexagonale du projet Mangarr — structure exacte des dossiers, règles d'import strictes par couche, nommage ports (interfaces) vs adapters (implémentations). Utiliser quand on crée un nouveau domaine, un nouveau fichier, ou qu'on vérifie les dépendances entre couches.
|
||||
allowed-tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# Architecture Hexagonale — Mangarr
|
||||
|
||||
## Structure canonique d'un domaine
|
||||
|
||||
```
|
||||
src/Domain/{DomainName}/
|
||||
Domain/ ← NOYAU pur, 0 dépendance framework
|
||||
Model/
|
||||
{Aggregate}.php
|
||||
ValueObject/
|
||||
{VoName}.php
|
||||
Event/
|
||||
{SomethingHappened}.php
|
||||
Exception/
|
||||
{Something}Exception.php
|
||||
Contract/ ← PORTS (interfaces only)
|
||||
Repository/
|
||||
{Name}RepositoryInterface.php
|
||||
Service/
|
||||
{Name}Interface.php
|
||||
Client/
|
||||
{Name}ClientInterface.php
|
||||
|
||||
Application/ ← Use cases, orchestre le Domain
|
||||
Command/
|
||||
{DoSomething}.php
|
||||
CommandHandler/
|
||||
{DoSomething}Handler.php
|
||||
Query/
|
||||
{GetSomething}.php
|
||||
QueryHandler/
|
||||
{GetSomething}Handler.php
|
||||
Response/
|
||||
{Something}Response.php
|
||||
EventListener/
|
||||
{SomethingHappened}EventListener.php
|
||||
|
||||
Infrastructure/ ← ADAPTERS (implémentations concrètes)
|
||||
Persistence/
|
||||
Repository/
|
||||
{Name}Repository.php ← implémente Domain/Contract/Repository/
|
||||
ApiPlatform/
|
||||
Resource/
|
||||
{FeatureName}Resource.php
|
||||
State/
|
||||
Processor/
|
||||
{DoSomething}Processor.php
|
||||
Provider/
|
||||
{GetSomething}StateProvider.php
|
||||
Dto/
|
||||
{Name}.php
|
||||
Service/
|
||||
{ServiceName}.php ← implémente Domain/Contract/Service/
|
||||
Client/
|
||||
{ClientName}.php ← implémente Domain/Contract/Client/
|
||||
CommandHandler/ ← handlers Symfony Messenger (wrappent l'Application)
|
||||
Symfony{DoSomething}Handler.php
|
||||
```
|
||||
|
||||
## Domaines du projet
|
||||
|
||||
| Domaine | Responsabilité |
|
||||
|-------------|-----------------------------------------------------|
|
||||
| `Manga` | Catalogue mangas, chapitres, métadonnées |
|
||||
| `Scraping` | Téléchargement de chapitres depuis les sources |
|
||||
| `Conversion`| Conversion de formats (CBR→CBZ, génération CBZ) |
|
||||
| `Reader` | Lecture de chapitres |
|
||||
| `Setting` | Configuration applicative |
|
||||
| `Shared` | Contrats transverses (`EventDispatcherInterface`, `MangaPathManagerInterface`, etc.) |
|
||||
|
||||
## Règles d'import strictes
|
||||
|
||||
### Domain (noyau)
|
||||
```
|
||||
✅ Peut importer : son propre namespace uniquement
|
||||
+ exceptions PHP standard
|
||||
❌ Interdit : Symfony\*, Doctrine\*, Ramsey\Uuid, tout autre domaine
|
||||
```
|
||||
|
||||
### Application
|
||||
```
|
||||
✅ Peut importer : son propre Domain (App\Domain\{X}\Domain\*)
|
||||
App\Domain\Shared\Domain\Contract\*
|
||||
Symfony\Component\Messenger\*
|
||||
Ramsey\Uuid\*
|
||||
❌ Interdit : son propre Infrastructure (App\Domain\{X}\Infrastructure\*)
|
||||
Doctrine\*, tout autre domaine
|
||||
```
|
||||
|
||||
### Infrastructure
|
||||
```
|
||||
✅ Peut importer : tout (Symfony, Doctrine, API Platform, etc.)
|
||||
son Application et son Domain
|
||||
❌ Convention : ne pas contenir de logique métier (déléguer à Application)
|
||||
```
|
||||
|
||||
## Ports vs Adapters — nommage
|
||||
|
||||
| Concept | Localisation | Suffixe | Exemple |
|
||||
|-----------|--------------------------------------|-----------------|---------------------------------|
|
||||
| Port | `Domain/Contract/Repository/` | `Interface` | `MangaRepositoryInterface` |
|
||||
| Port | `Domain/Contract/Service/` | `Interface` | `ImageProcessorInterface` |
|
||||
| Port | `Domain/Contract/Client/` | `Interface` | `MangadexClientInterface` |
|
||||
| Adapter | `Infrastructure/Persistence/` | `Repository` | `LegacyChapterRepository` |
|
||||
| Adapter | `Infrastructure/Service/` | *(nom libre)* | `ImageProcessor` |
|
||||
| Adapter | `Infrastructure/Client/` | `Client` | `MangadexClient` |
|
||||
|
||||
Le binding port → adapter se déclare dans `config/services.yaml` :
|
||||
```yaml
|
||||
App\Domain\Manga\Domain\Contract\Repository\MangaRepositoryInterface:
|
||||
alias: App\Domain\Manga\Infrastructure\Persistence\Repository\LegacyMangaRepository
|
||||
```
|
||||
|
||||
## Shared Domain
|
||||
|
||||
Les contrats transverses vivent dans `src/Domain/Shared/Domain/Contract/` :
|
||||
- `CommandInterface`, `QueryInterface`, `ResponseInterface` — marqueurs
|
||||
- `CommandHandlerInterface`, `QueryHandlerInterface` — handlers génériques
|
||||
- `EventDispatcherInterface` — dispatch d'événements domain
|
||||
- `MangaPathManagerInterface` — gestion des chemins de fichiers
|
||||
- `FileUploadInterface`, `NotificationInterface` — services transverses
|
||||
|
||||
`App\Domain\Shared` **ne dépend de personne** (règle PHPArkitect).
|
||||
|
||||
## Checklist avant de créer un fichier
|
||||
|
||||
1. Dans quelle couche va ce fichier ? (Domain / Application / Infrastructure)
|
||||
2. Ce fichier va-t-il importer quelque chose d'interdit pour cette couche ?
|
||||
3. Si c'est une implémentation concrète → existe-t-il déjà une interface (port) dans `Domain/Contract/` ?
|
||||
4. Si c'est une nouvelle interface → est-elle dans `Domain/Contract/` et non dans Infrastructure ?
|
||||
5. Le binding alias est-il déclaré dans `config/services.yaml` ?
|
||||
|
||||
Vérification automatique : `make phparkitect`
|
||||
Reference in New Issue
Block a user