Conventions API
L’API SIM est versionnée par URI, validée avec class-validator, et retourne une enveloppe d’erreur uniforme. Les contrôleurs restent minces ; l’orchestration vit dans les services et le SQL dans les repositories.
Versioning et chemins de base
Section intitulée « Versioning et chemins de base »Les contrôleurs déclarent à la fois le chemin du module et la version :
@Controller({ path: 'residence', version: '1' })Toutes les routes protégées sont préfixées par /api/v1. /metrics est exclu du préfixe api et est public.
Contrôleurs
Section intitulée « Contrôleurs »Les contrôleurs sont responsables de :
- routage et mapping des méthodes HTTP
- décorateurs Swagger (
@ApiTags,@ApiBearerAuth,@ApiPropertysur les DTO) - décorateurs d’authentification / autorisation (
@Public,@RequirePermissions,@CurrentUser) - extraction des DTO et paramètres, puis appel des services
DTO et validation
Section intitulée « DTO et validation »Les DTO sont des classes, importées en valeur dans les contrôleurs pour que emitDecoratorMetadata fonctionne.
export class CreerClientDto { @IsString() @IsNotEmpty() nom: string;
@IsOptional() @IsString() @Matches(DATE_PATTERN) date_naissance?: string | null;}Pipe de validation global :
app.useGlobalPipes( new ValidationPipe({ transform: true, whitelist: true }),);Les unions d’enums générées sont en type seulement, donc la validation runtime utilise des tableaux @IsIn écrits à la main.
Décorateurs courants
Section intitulée « Décorateurs courants »| Décorateur | Rôle |
|---|---|
@Public() |
Ignore le JWT sur cette route |
@RequirePermissions('MODULE.ACTION') |
Codes de permission requis |
@CurrentUser() |
Injecte request.user en AuthUser |
@Backpressure() |
Marque la route pour le contrôle de profondeur de file |
JwtAuthGuard
Section intitulée « JwtAuthGuard »- ignore
@Public() - extrait le jeton Bearer
- vérifie signature et expiration
- contrôle la denylist
jtiRedis - résout permissions,
idClient,idCaisse,idActiviteScope - attache
AuthUseràrequest.user
PermissionsGuard
Section intitulée « PermissionsGuard »- lit les métadonnées
@RequirePermissions - autorise si vide
- sinon vérifie que toutes les permissions listées sont dans
user.permissions
BackpressureGuard
Section intitulée « BackpressureGuard »- rejette les routes
@Backpressure()avec503quand les jobswaiting + activedépassentBACKPRESSURE_QUEUE_DEPTH(défaut 100 ;0désactive)
Enveloppe d’erreur
Section intitulée « Enveloppe d’erreur »AllExceptionsFilter retourne une forme JSON uniforme :
{ "success": false, "statusCode": 400, "code": "DATA_ERROR", "message": "...", "details": [...], "requestId": "...", "path": "/api/v1/client/clients", "timestamp": "..."}Mappages SQLSTATE PostgreSQL :
| SQLSTATE | Statut HTTP | code |
|---|---|---|
23505 |
409 | CONFLICT |
23503 |
422 | FK_VIOLATION |
23502 / 23514 |
400 | DATA_ERROR |
22P02 |
400 | DATA_ERROR |
pino logue en JSON. requestId vient de l’en-tête x-request-id ou d’un randomUUID(). La réponse renvoie x-request-id. Les champs sensibles sont rédigés : authorization, cookie, *_token, mot_de_passe.
Patrons courants par contrôleur
Section intitulée « Patrons courants par contrôleur »@Post()@RequirePermissions('CLIENT.CREER')async creer( @Body() dto: CreerClientDto, @CurrentUser() user: AuthUser,) { return this.service.creer(dto, user.id);}Pour les endpoints de liste, les DTO de requête étendent ListQueryDto :
export class ListerClientsDto extends ListQueryDto { @IsOptional() @IsString() type_client?: string;
@IsOptional() @IsString() recherche?: string;}