Décorateurs
Pour garder notre code propre et déclaratif, nous utilisons des Décorateurs Personnalisés pour les préoccupations transverses comme le Cache et la Gestion d'Erreurs.
Décorateurs de Service
Ils sont principalement utilisés dans la couche Service pour gérer le cache Redis de manière transparente.
@Cacheable
Met automatiquement en cache le résultat d'une méthode dans Redis.
- Usage : Opérations de lecture (getters).
- Comportement : Vérifie le cache -> Retourne si HIT -> Exécute la méthode si MISS -> Stocke le résultat.
import { Cacheable } from "#decorators/cacheable";
class UserService {
@Cacheable({
namespace: "users",
ttl: 300, // 5 minutes
})
async getUser(id: number) {
return await User.find(id);
}
}
// Clé Cache : users:getUser:[1]
Options :
namespace: Clé de groupement (ex: 'cameras').ttl: Durée de vie en secondes.keyGenerator: Fonction personnalisée pour construire la clé.condition: Fonction retournant un booléen (ex: ne pas mettre en cache pour les admins).
@CacheById
Un raccourci pour @Cacheable lorsque la clé de cache est un seul ID. Il génère une clé plus propre namespace:id:{valeur}.
@CacheById({ namespace: 'cameras' })
async getById(id: number) { ... }
// Clé Cache : cameras:id:1
@InvalidateCache
Nettoie le cache obsolète après une opération d'écriture.
- Usage : Méthodes Create, Update, Delete.
- Patterns : Supporte les wildcards (
*).
import { InvalidateCache } from "#decorators/cacheable";
class UserService {
@InvalidateCache({
namespace: "users",
patterns: ["getUser:*", "list:*"],
})
async updateUser(id: number, data: any) {
// ... logique de mise à jour
}
}
Décorateurs de Contrôleur
Ils sont utilisés dans les Contrôleurs pour standardiser le traitement des requêtes.
@HandleError
Enveloppe toute l'action du contrôleur dans un bloc try/catch.
- BusinessException : Renvoyée (gérée par le Handler Global -> 4xx).
- Erreur Inconnue : Attrapée, Loggée avec Contexte (User, URL), et retourne 500 "Internal Server Error".
import { HandleError } from "#decorators/handle_error";
class CameraController {
@HandleError("Échec de récupération des caméras")
async index({ response }) {
// ...
}
}
@WithPagination
Parse automatiquement ?limit=10&offset=0 depuis la query string et l'injecte dans le contexte.
import { WithPagination } from "#decorators/handle_error";
class CameraController {
@WithPagination
async index({ pagination }: HttpContext & { pagination: any }) {
console.log(pagination.limit); // 10
}
}