feat: ajout de rules pour cursor
This commit is contained in:
parent
fe92e53be7
commit
19a697c712
213
.cursor/rules/api_platform.mdc
Normal file
213
.cursor/rules/api_platform.mdc
Normal file
@@ -0,0 +1,213 @@
|
||||
---
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
# API Platform dans Mangarr
|
||||
|
||||
## Structure de l'API
|
||||
L'API est organisée dans la couche Infrastructure de chaque domaine :
|
||||
|
||||
```
|
||||
Domain/Manga/Infrastructure/ApiPlatform/
|
||||
├── Resource/ # Configuration des ressources API
|
||||
│ └── MangaResource.php
|
||||
├── State/ # Providers et Processors
|
||||
├── Provider/ # State Providers
|
||||
└── Processor/ # State Processors
|
||||
|
||||
```
|
||||
|
||||
## Règles d'Organisation
|
||||
|
||||
### 1. Resources
|
||||
- Localisation : `Infrastructure/ApiPlatform/Resource/`
|
||||
- Principes :
|
||||
- Une classe = une ressource API
|
||||
- Documentation exhaustive avec les attributs PHP 8
|
||||
- Validation contraintes avec les attributs Symfony
|
||||
- Nommage : `{Nom}Resource`
|
||||
|
||||
### 2. State Providers/Processors
|
||||
- Localisation : `Infrastructure/ApiPlatform/State/`
|
||||
- Principes :
|
||||
- Utiliser les cas d'utilisation du domaine (Commands/Queries)
|
||||
- Ne pas contenir de logique métier
|
||||
- Conversion Resource ↔ Command/Query
|
||||
- Nommage : `{Action}{Resource}StateProvider/Processor`
|
||||
|
||||
## Exemples de Code
|
||||
|
||||
### 1. Resource API
|
||||
```php
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\Resource;
|
||||
|
||||
use ApiPlatform\Metadata\ApiResource;
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider\GetMangaStateProvider;
|
||||
use App\Domain\Manga\Infrastructure\ApiPlatform\State\Processor\CreateMangaStateProcessor;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ApiResource(
|
||||
shortName: 'Manga',
|
||||
operations: [
|
||||
new Get(
|
||||
uriTemplate: '/mangas/{id}',
|
||||
provider: GetMangaStateProvider::class,
|
||||
description: 'Récupère un manga par son identifiant',
|
||||
openapi: [
|
||||
'summary' => 'Récupère un manga',
|
||||
'200' => [
|
||||
'description' => 'Manga trouvé',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'id' => ['type' => 'string', 'format' => 'uuid'],
|
||||
'title' => ['type' => 'string'],
|
||||
'description' => ['type' => 'string', 'nullable' => true],
|
||||
'authors' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'string']
|
||||
],
|
||||
'coverUrl' => ['type' => 'string', 'format' => 'uri', 'nullable' => true]
|
||||
],
|
||||
'required' => ['id', 'title', 'authors']
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'404' => [
|
||||
'description' => 'Manga non trouvé'
|
||||
]
|
||||
]
|
||||
),
|
||||
new Post(
|
||||
uriTemplate: '/mangas',
|
||||
processor: CreateMangaStateProcessor::class,
|
||||
description: 'Crée un nouveau manga',
|
||||
openapi: [
|
||||
'requestBody' => [
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'title' => ['type' => 'string'],
|
||||
'description' => ['type' => 'string', 'nullable' => true],
|
||||
'authors' => [
|
||||
'type' => 'array',
|
||||
'items' => ['type' => 'string']
|
||||
],
|
||||
'coverUrl' => ['type' => 'string', 'format' => 'uri', 'nullable' => true]
|
||||
],
|
||||
'required' => ['title']
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
'responses' => [
|
||||
'201' => [
|
||||
'description' => 'Manga créé'
|
||||
],
|
||||
'400' => [
|
||||
'description' => 'Données invalides'
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
]
|
||||
)]
|
||||
class MangaResource
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
### 2. State Provider
|
||||
```php
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\State\Provider;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Domain\Manga\Application\Query\GetMangaByIdQuery;
|
||||
use App\Domain\Shared\Contract\Response;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
class GetMangaStateProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MessageBusInterface $queryBus
|
||||
) {}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?Response
|
||||
{
|
||||
$query = new GetMangaByIdQuery($uriVariables['id']);
|
||||
$response = $this->queryBus->dispatch($query);
|
||||
|
||||
if (null === $response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. State Processor
|
||||
```php
|
||||
namespace App\Domain\Manga\Infrastructure\ApiPlatform\State\Processor;
|
||||
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use App\Domain\Manga\Application\Command\CreateMangaCommand;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
class CreateMangaStateProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MessageBusInterface $commandBus
|
||||
) {}
|
||||
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
|
||||
{
|
||||
assert($data instanceof MangaResource);
|
||||
|
||||
$command = new CreateMangaCommand(
|
||||
title: $data->title,
|
||||
description: $data->description,
|
||||
authors: $data->authors,
|
||||
coverUrl: $data->coverUrl
|
||||
);
|
||||
|
||||
$this->commandBus->dispatch($command);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Bonnes Pratiques
|
||||
|
||||
### 1. Documentation
|
||||
- Documentation exhaustive des endpoints
|
||||
- Description claire des paramètres
|
||||
- Exemples de requêtes/réponses
|
||||
- Documentation des codes d'erreur
|
||||
|
||||
### 2. Validation
|
||||
- Validation stricte des entrées
|
||||
- Groupes de validation par contexte
|
||||
- Messages d'erreur explicites
|
||||
- Validation des types et formats
|
||||
|
||||
### 3. Sécurité
|
||||
- Définition claire des accès
|
||||
- Validation des permissions
|
||||
- Sanitization des entrées
|
||||
- Gestion des erreurs sécurisée
|
||||
|
||||
### 4. Performance
|
||||
- Pagination par défaut
|
||||
- Sélection des champs (sparse fieldsets)
|
||||
- Gestion des includes (relationships)
|
||||
- Cache approprié
|
||||
Reference in New Issue
Block a user