npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

anatix-tools

v1.0.6

Published

Anatix toolkit pour NestJS avec event-bus, logger, proxy, decorators et utils.

Readme

🧰 anatix-tools – Librairie utilitaire NestJS pour Anatix-Generator

anatix-tools est une boîte à outils Node.js/TypeScript pour NestJS, utilisée dans le générateur de microservices Anatix-Generator. Elle fournit un socle commun de fonctionnalités (communication inter-services, journalisation centralisée, appels HTTP uniformisés, etc.) pour standardiser et simplifier le développement des microservices dans l'écosystème Anatix. La librairie regroupe plusieurs modules clés (bus d'événements, gestionnaire de logs, proxy HTTP, filtre global d'erreurs, utilitaires divers) destinés à être intégrés dans chaque microservice, garantissant une architecture cohérente et des bonnes pratiques partagées.


✨ Fonctionnalités principales

  • 📢 Bus d'événements centralisé (basé sur RabbitMQ) permettant la communication asynchrone et découplée entre microservices.

  • 📝 Journalisation unifiée des logs via le bus d'événements, pour centraliser et corréler les journaux de tous les services.

  • 🌐 Proxy HTTP pour les appels inter-services avec gestion automatique des délais d'attente (timeout), des nouvelles tentatives (retry) et des erreurs (exceptions HTTP homogénéisées).

  • ⚠️ Filtre global d'exceptions assurant un traitement uniforme des erreurs et des réponses cohérentes en cas d'échec dans les API.

  • 🛠️ Utilitaires généraux (formatage de dates, parsing de paramètres, etc.) évitant la duplication de code commun dans les microservices.


📦 Installation

Cette librairie est distribuée via npm. Pour l'ajouter à votre projet NestJS :

npm install anatix-tools

Prérequis : Assurez-vous de disposer d'une application NestJS (v10+) fonctionnelle avant d'intégrer Anatix-Tools. Ce package repose sur plusieurs peer dependencies (telles que @nestjs/common@nestjs/core@nestjs/microservicesrxjsclass-validatorclass-transformer...), qui doivent déjà être présentes dans votre projet NestJS.


⚙️ Configuration & Dépendances

Certains composants d'Anatix-Tools nécessitent une configuration par variables d'environnement et des services externes :

  • RabbitMQ : un serveur RabbitMQ est requis pour le bus d'événements. Configurez l'URL de connexion via la variable RABBITMQ_URL (par défaut amqp://localhost). Assurez-vous qu'une instance RabbitMQ est accessible à cette adresse.

  • Échange et file d'événements : par défaut, le bus utilise l'échange anatix-event-bus (modifiable via EVENT_BUS_EXCHANGE) et une file de messages nommée default-queue (modifiable via EVENT_BUS_QUEUE). Il est conseillé de définir pour chaque microservice un nom de queue distinct via EVENT_BUS_QUEUE afin que chaque service reçoive uniquement les événements qui lui sont destinés.

  • Timeout et retries HTTP : les fonctions de proxy HTTP utilisent une valeur par défaut de 5000 ms pour le timeout (PROXY_TIMEOUT_MS) et effectuent 2 tentatives en cas d'échec (PROXY_RETRY). Vous pouvez ajuster ces valeurs via les variables d'environnement correspondantes.

  • Autres dépendances : assurez-vous d'avoir ajouté le module HttpModule de NestJS (fournissant HttpService) dans vos microservices si vous utilisez les proxies HTTP. Le filtre global d'exceptions utilise le framework Web par défaut de Nest (Express) pour formater la réponse d'erreur.

En résumé, vérifiez que vos variables d'environnement (fichier .env ou autre) sont correctement définies pour RabbitMQ et les paramètres de proxy, et que les services requis (comme RabbitMQ) sont opérationnels avant de démarrer vos microservices.


📁 Structure du code et modules

anatix-tools/
├── packages/
│   ├── event-bus/         # 🔄 Bus d'événements basé sur RabbitMQ (EventBusModule & Service)
│   ├── logger/            # 📝 Journalisation centralisée via le bus d'événements (LogHelper, DTO de log)
│   ├── proxy/             # 🌐 Proxy HTTP pour appels externes (fonctions GET/POST/... avec retry)
│   ├── decorators/        # 🎖️ Filtre global d'exceptions NestJS (GlobalExceptionFilter)
│   ├── utils/             # 🛠️ Fonctions utilitaires diverses (dates, filtres, etc.)
│   └── constants.ts       # ⚙️ Constantes de configuration globales (RabbitMQ, timeouts, etc.)
├── package.json
└── ...

Les principaux modules inclus dans la librairie sont détaillés ci-dessous :

Event Bus (Bus d'événements)

Le module Event Bus fournit un EventBusModule et un service EventBusService permettant la communication asynchrone entre microservices via RabbitMQ. À l'initialisation, le service établit une connexion AMQP en utilisant l'URL fournie (RABBITMQ_URL), déclare un exchange de type topic (par défaut nommé anatix-event-bus) et une queue dédiée au microservice (nom définissable via EVENT_BUS_QUEUE).

  • Émission d'événements : la méthode emit(eventName, payload) publie un message sur le bus avec une clé de routage correspondant au nom de l'événement. Tous les microservices ayant souscrit à cet événement recevront le message (via leur propre queue).

  • Souscription aux événements : le EventBusService permet de s'abonner à un type d'événement grâce à une méthode dédiée (par ex. subscribe(eventName, handler)). Lorsqu'un microservice s'abonne à un événement, le service va lier sa queue RabbitMQ à l'exchange sur la clé de routage correspondante, puis appeler la fonction de handler fournie à chaque fois qu'un message de ce type est reçu.

  • Communication découplée : ce système de publication/souscription permet un couplage lâche entre services. Un microservice peut émettre des événements sans se préoccuper de qui les consomme, et réciproquement écouter certains événements produits par d'autres services, ce qui facilite l'extensibilité et la résilience de l'architecture.

  • Requêtes avec réponse (RPC) : en plus des événements "one-way", le bus prend en charge un mode requête/réponse. La méthode emitAndWait(eventName, payload, timeout?) émet un événement en attendant explicitement une réponse. Sous le capot, le service crée une queue éphémère de réponse et utilise un correlation ID pour corréler la réponse attendue. Cela permet d'implémenter des appels synchrones (de type RPC) entre microservices tout en passant par RabbitMQ.

Pour utiliser le bus d'événements dans un microservice Anatix, importez simplement EventBusModule dans le module principal du service. Le EventBusService pourra alors être injecté dans vos services ou controllers NestJS afin d'émettre des événements ou de s'y abonner selon les besoins.

Logger (Journalisation centralisée)

Le module Logger offre un mécanisme de logs centralisés en s'appuyant sur le bus d'événements. La classe principale, LogHelper, s'utilise pour enregistrer des journaux structurés sans dépendre d'un fichier local ou de la console de chaque microservice.

  • Log via EventBus : au lieu d'écrire directement dans la console, LogHelper envoie chaque log sous forme d'événement sur le bus. Pour ce faire, on instancie un LogHelper avec une référence vers le EventBusService et le nom du microservice courant. Par exemple : const logger = new LogHelper(eventBusService, 'UserService').

  • Niveaux de log : le helper propose des méthodes correspondant aux différents niveaux de log : info()warn()error(), et critical(). Chaque appel construit un objet de log structuré (défini par le DTO CreateLogDto avec les champs : service émetteur, niveau, message, métadonnées éventuelles, utilisateur, tag, stack trace) puis publie un événement sur le bus d'événements. Par convention, les événements de log utilisent une clé de routage dédiée, par ex. log.UserService, ce qui permet de filtrer/diriger ces messages spécifiquement.

  • Traitement des erreurs critiques : la méthode critical() enregistre un log de niveau ERROR puis lance une exception correspondante. Concrètement, si l'erreur passée est une exception HTTP connue (HttpException), elle sera relancée telle quelle. Sinon, une exception générique InternalServerErrorException (500) est levée après journalisation. Cela permet de centraliser le pattern de gestion des erreurs fatales : loguer l'erreur et interrompre le flux d'exécution de manière appropriée.

  • Agrégation centralisée : en publiant tous les logs sur le bus (par exemple avec la clé de routage log.*), il devient possible de mettre en place un microservice de collecte des logs ou tout autre consommateur écoutant ces événements pour stocker ou analyser les journaux de l'ensemble du système de microservices.

En résumé, le module Logger d'Anatix-Tools permet à chaque service de pousser ses logs dans un canal commun (RabbitMQ) plutôt que de simplement les afficher en local, offrant ainsi la possibilité d'un monitoring et d'une analyse centralisés des événements de log.

Proxy HTTP (Appels externes)

Le module Proxy regroupe des fonctions utilitaires facilitant les appels HTTP sortants depuis un microservice (typiquement pour appeler un autre service Anatix ou une API externe). Plutôt que d'utiliser directement un client HTTP basique, ces fonctions proxy apportent robustesse et simplification en gérant pour vous les points suivants :

  • Timeout global : chaque requête est soumise à un délai maximal (par défaut 5000 ms, configurable via PROXY_TIMEOUT_MS). Au-delà, une exception de type HttpException 504 Gateway Timeout est automatiquement levée pour signaler l'indisponibilité du service cible.

  • Retries automatisés : en cas d'échec transitoire (par exemple, service temporairement inaccessible), le proxy retente automatiquement la requête selon un nombre prédéfini de tentatives (2 retries par défaut, via PROXY_RETRY). Ceci augmente la résilience face aux erreurs réseau momentanées.

  • Propagation des erreurs HTTP : si le service appelé retourne une réponse d'erreur (code HTTP 4xx ou 5xx), la fonction proxy relaie cette erreur sous forme d'exception NestJS contenant le même code statut et le message d'erreur retourné. Votre microservice peut ainsi renvoyer directement l'erreur au client appelant, sans traitement manuel, tout en conservant le code approprié.

  • Simplicité d'utilisation : cinq fonctions sont disponibles – proxyGetproxyPostproxyPutproxyPatchproxyDelete – correspondant aux verbes HTTP. Chacune attend en paramètre une instance de HttpService (de NestJS) ainsi que l'URL cible, et éventuellement des paramètres de requête, un corps (pour POST/PUT/PATCH) ou des en-têtes. La fonction retourne une promesse résolue avec les données de la réponse en cas de succès, ou rejette une exception en cas d'erreur (timeout, statut d'erreur, etc.).

Pour utiliser ces proxies, assurez-vous d'avoir importé le HttpModule de @nestjs/axios dans votre microservice (afin de pouvoir injecter HttpService). Vous pouvez ensuite appeler, par exemple, await proxyGet(httpService, 'http://autre-service/api/endpoint', queryParams) depuis un service NestJS. Vous bénéficierez ainsi d'appels HTTP fiables et uniformisés, avec gestion automatique des exceptions, sans avoir à répéter le même code de contrôle des erreurs dans chaque appel.

Filtre global d'exceptions

Le module Decorators contient principalement le GlobalExceptionFilter, un filtre d'exception NestJS conçu pour uniformiser le traitement des erreurs non gérées dans l'application. En déclarant ce filtre au niveau global (via un provider { provide: APP_FILTER, useClass: GlobalExceptionFilter } ou en l'enregistrant dans le bootstrap de l'application avec app.useGlobalFilters(new GlobalExceptionFilter())), vous centralisez la gestion des erreurs.

  • Gestion des HttpException : Si l'exception interceptée est une instance de HttpException (erreur volontairement levée dans le code applicatif, par exemple pour signaler une ressource non trouvée ou un accès interdit), le filtre extrait le code HTTP et le message/objet de réponse de cette exception et les utilise tels quels dans la réponse.

  • Gestion des erreurs système : Pour toute autre erreur (erreur non prévue, exception JavaScript, etc.), le filtre attribue un code HTTP 500 Internal Server Error et un message générique "Internal server error".

  • Réponse uniformisée : Le filtre construit une réponse JSON standard contenant toujours le champ statusCode (code numérique), path (l'URL de la requête ayant causé l'erreur), un timestamp ISO (timestamp) et un champ message pouvant être soit un texte explicatif, soit un objet détaillant l'erreur. Ce format de sortie cohérent facilite le traitement côté client et le diagnostic.

  • Logging intégré : À chaque exception interceptée, le filtre utilise la classe Logger de NestJS pour consigner l'erreur (méthode HTTP, URL et contenu de l'erreur) dans la console du serveur. Ceci assure une traçabilité des erreurs même si aucun système de log externe n'est encore en place.

Grâce à GlobalExceptionFilter, les microservices Anatix partagent tous la même politique de gestion des erreurs : l'équipe de développement n'a pas besoin d'implémenter manuellement la sérialisation d'erreurs dans chaque contrôleur, et les clients des API reçoivent systématiquement des réponses d'erreur structurées de la même manière.

Utilitaires (fonctions communes)

Le module Utils rassemble des fonctions utilitaires pour les besoins courants des microservices :

  • toISOStringSafe(value) : convertit une date en chaîne ISO (format UTC) de manière sûre. Si value est un objet Date, la méthode renvoie value.toISOString(). Si c'est une chaîne ou un timestamp numérique, elle tente de le convertir en Date puis en ISO. En cas de valeur invalide ou non convertible, la fonction retourne une chaîne vide plutôt que de produire une erreur.

  • toDateOnlyString(value) : extrait la partie date (format YYYY-MM-DD) d'une date ou d'une chaîne date/heure. Si value est un objet Date, la date est formatée en ISO puis tronquée au jour uniquement. Si c'est une chaîne (par ex. "2025-07-16T12:00:00Z"), la fonction ne conserve que la portion avant le T. Utile pour normaliser des dates sans composante horaire (par ex. pour comparer des dates de naissance, etc.).

  • parseFilterFields(filters, defs) : fonction de parsage des filtres très pratique pour traiter les paramètres de requête HTTP. Elle prend en entrée un objet filters (typiquement issu des query params de l'URL) et un objet de définition defs de type FilterFieldDefs qui spécifie le type attendu pour certains champs. La fonction retourne un nouvel objet où chaque champ est converti selon les règles fournies dans defs :

    • date : les champs listés dans defs.date (p. ex. createdAt) sont convertis de chaîne en objet Date. De plus, si un champ est suffixé par "From" ou "To" (p. ex. createdAtFrom), il sera également converti en Date, ce qui facilite la gestion des intervalles de dates.

    • dateOnly : pour les champs purement date (liste defs.dateOnly), la valeur est transformée en chaîne "YYYY-MM-DD" sans composante horaire (si une heure était présente, elle est ignorée).

    • number : les champs numériques (liste defs.number) sont convertis de chaîne en valeur Number. S'ils sont suffixés "From"/"To", la conversion s'applique de la même manière.

    • boolean : les champs booléens (defs.boolean) acceptent en entrée les chaînes "true"/"1" (converties en true) ou "false"/"0" (converties en false).

    • enum : pour les champs énumérés (defs.enum), la fonction vérifie que la valeur fournie fait partie des valeurs autorisées définies dans defs.enumValues. Si ce n'est pas le cas, deux stratégies sont possibles : soit lever une erreur (si throwOnInvalidEnum est à true dans la définition), soit simplement supprimer ce filtre non valide du résultat (le champ est ignoré).

    • array : pour les champs qui doivent être des listes (defs.array), si la valeur d'entrée est une chaîne comportant des virgules, elle sera découpée en un tableau (séparation sur , avec suppression des espaces inutiles).

    • json : pour les champs devant contenir du JSON (defs.json), si la valeur est une chaîne, la fonction tentera de la parser avec JSON.parse pour obtenir un objet JavaScript (en cas d'échec du parsing, la valeur d'origine est laissée telle quelle).

    • custom : il est possible de définir dans defs.custom un objet de la forme { champ: transformFn } pour appliquer une transformation personnalisée à certains champs. Si un champ est présent dans filters et qu'une fonction custom est fournie pour ce champ, la valeur sera transformée par cette fonction.

Grâce à parseFilterFields, le code d'un contrôleur peut aisément convertir en quelques lignes l'ensemble de ses paramètres de recherche (query) en types natifs appropriés, au lieu de vérifier et convertir chaque champ manuellement. Cela contribue à des contrôleurs plus concis et fiables.


En conclusion, Anatix-Tools fournit une base solide pour construire des microservices NestJS cohérents et robustes. En intégrant ce toolkit, les microservices générés par Anatix-Generator partagent une structure commune pour la communication (événements), le logging, la gestion des erreurs et les utilitaires de traitement, ce qui accélère le développement tout en améliorant la maintenabilité et l'homogénéité de l'ensemble de la plateforme Anatix.