@aventii/link (1.0.0)

Published 2026-08-19 16:47:48 +00:00 by Valentin

Installation

@aventii:registry=
npm install @aventii/link@1.0.0
"@aventii/link": "1.0.0"

About this package

@aventii/link

Utilitaires de communication HTTP entre les microservices Aventii.

@aventii/link fournit une couche commune pour :

  • créer des clients HTTP inter-MS ;
  • transporter automatiquement le token d'authentification interne ;
  • transmettre un contexte utilisateur et pays de confiance ;
  • recevoir et valider ce contexte côté microservice ;
  • relayer les requêtes depuis un gateway vers les microservices ;
  • utiliser différents transports HTTP sans coupler le reste du code à Fetch ou Axios.

Le paquet ne gère pas les secrets eux-mêmes et ne dépend pas de pmc-keys.


Installation

npm install @aventii/link

Axios n'est nécessaire que si createAxiosTransport est utilisé :

npm install axios

Le transport Fetch repose sur l'API Fetch native de Node.js.


API publique

const {
    createServiceClient,
    ServiceRequestError,

    createInternalContextMiddleware,
    requireUserContext,
    requireCountryContext,

    createGatewayProxy,

    createFetchTransport,
    createAxiosTransport
} = require('@aventii/link');

Client inter-MS

createServiceClient(options)

Crée un client associé à un microservice donné.

Le client utilise une URL de base fixe, récupère le token interne via getAuthToken, peut transmettre x-user-id et x-country depuis un contexte explicitement fourni, protège ces headers contre une surcharge directe par le consommateur, gère les query params et les corps JSON, puis délègue l'exécution HTTP à un transport.

Exemple

const { createServiceClient, createFetchTransport } = require('@aventii/link');

const access = createServiceClient({
    baseUrl: process.env.ACCESS_URL,
    getAuthToken,
    transport: createFetchTransport()
});

const response = await access.request({
    method: 'GET',
    path: '/api/user/123'
});

console.log(response.data);

Le nom du client appartient au consommateur. Plusieurs connecteurs peuvent naturellement coexister :

const access = createServiceClient({ ... });
const di = createServiceClient({ ... });
const notif = createServiceClient({ ... });

await access.request({ ... });
await di.request({ ... });
await notif.request({ ... });

client.request(options)

Envoie une requête vers le microservice associé au client.

await client.request({
    method: 'POST',
    path: '/api/example',
    query: { active: true },
    body: { value: 42 },
    context: {
        userId: '...',
        country: 'CM'
    },
    headers: {
        'x-custom-header': 'value'
    },
    timeoutMs: 5000,
    stream: false
});

La réponse normalisée possède la forme :

{
    status,
    headers,
    data
}

Une réponse HTTP hors plage 2xx provoque une ServiceRequestError.


Contexte inter-MS

Le protocole peut transporter deux informations de contexte :

x-user-id
x-country

Ces headers ne doivent pas être considérés comme fiables lorsqu'ils proviennent directement d'un client public. Ils sont supprimés puis reconstruits par les composants Aventii à partir d'un contexte de confiance.

Le pays est normalisé sous forme de code à deux lettres en majuscules, par exemple CM, MG ou FR.

createInternalContextMiddleware(options)

Crée un middleware destiné aux microservices recevant des appels internes. Il vérifie le token inter-MS puis construit :

req.internalContext

Exemple :

{
    userId: '...',
    country: 'CM'
}

Utilisation :

const { createInternalContextMiddleware } = require('@aventii/link');

app.use(createInternalContextMiddleware({
    isValidToken: checkInternalToken
}));

requireUserContext

Middleware exigeant la présence d'un utilisateur dans le contexte interne.

app.get('/private', requireUserContext, handler);

L'identifiant est ensuite disponible via :

req.internalContext.userId

requireCountryContext

Middleware exigeant la présence d'un pays valide dans le contexte interne.

app.get('/country-specific', requireCountryContext, handler);

Le pays est disponible via :

req.internalContext.country

Gateway

createGatewayProxy(options)

Crée un middleware Express capable de relayer une requête vers le microservice correspondant à une table de routes.

Le gateway sélectionne la destination, retire les informations sensibles fournies directement par le client, remplace le token d'autorisation par le token inter-MS, injecte éventuellement l'identifiant utilisateur et le pays depuis des fonctions de confiance, transmet les corps et flux, puis relaie la réponse du microservice.

Les détails techniques des erreurs internes ne sont pas publiés au client.

Exemple

const { createGatewayProxy, createFetchTransport } = require('@aventii/link');

const proxy = createGatewayProxy({
    routes: [
        { prefix: '/di', target: process.env.DI_URL },
        { prefix: '/pics', target: process.env.PICS_URL }
    ],
    getAuthToken,
    getUserId: req => req.user?._id,
    getCountry: req => req.country,
    transport: createFetchTransport()
});

app.use(proxy);

Transports HTTP

La logique de communication de @aventii/link est indépendante de la bibliothèque HTTP utilisée.

Un transport doit exposer :

transport.request(options)

Deux transports sont fournis.

createFetchTransport(options)

Transport basé sur l'API Fetch native de Node.js.

const { createFetchTransport } = require('@aventii/link');

const transport = createFetchTransport();

Il prend notamment en charge les timeouts, JSON, texte, réponses sans contenu et streams.

Le module Node.js stream utilisé par ce transport est natif et ne nécessite aucune installation supplémentaire.

createAxiosTransport(options)

Transport basé sur Axios.

const axios = require('axios');
const { createAxiosTransport } = require('@aventii/link');

const transport = createAxiosTransport({ axios });

Axios est volontairement injecté par le consommateur. Le cœur du paquet n'est ainsi pas couplé à une implémentation HTTP particulière.


Streams

Les clients peuvent demander une réponse streamée :

const response = await pics.request({
    method: 'GET',
    path: '/image/123',
    stream: true
});

response.data.pipe(destination);

Le transport Fetch convertit les ReadableStream Web en streams Node.js afin d'exposer un comportement cohérent avec Axios.


Erreurs

ServiceRequestError

Les erreurs provenant d'un appel inter-MS sont normalisées sous forme de ServiceRequestError.

Propriétés disponibles :

err.name
err.code
err.status
err.data
err.method
err.url
err.cause

Les erreurs de transport peuvent notamment être normalisées avec les codes :

TIMEOUT
NETWORK_ERROR

Exemple :

try {
    await access.request({ path: '/api/user/123' });
} catch (err) {
    if (err instanceof ServiceRequestError) {
        console.error(err.code, err.status);
    }
}

Les messages générés par le paquet sont préfixés par [link] afin d'être facilement identifiables dans les logs.


Sécurité

@aventii/link distingue volontairement les données reçues d'un client public des informations inter-MS de confiance.

En particulier :

  • le header authorization d'origine n'est pas propagé par le gateway ;
  • x-user-id fourni directement par le client n'est pas considéré comme fiable ;
  • x-country fourni directement par le client n'est pas considéré comme fiable ;
  • ces valeurs sont reconstruites depuis les fonctions de confiance fournies au gateway ;
  • les erreurs réseau internes ne sont pas exposées telles quelles au client public ;
  • les détails techniques restent disponibles dans les logs serveur.

Le paquet ne doit pas recevoir directement les secrets maîtres de l'infrastructure. Il reçoit uniquement les fonctions nécessaires à leur utilisation, par exemple getAuthToken.


Philosophie

@aventii/link définit le protocole commun de communication entre les composants Aventii sans connaître leur métier.

Il ne doit pas savoir ce qu'est une réservation, une notification ou un utilisateur métier, quelles bases de données sont utilisées, ni comment les secrets maîtres sont stockés.

Il fournit uniquement les primitives communes permettant aux services de communiquer de manière homogène, contrôlée et interchangeable.

Dependencies

Development Dependencies

ID Version
jest ^30.0.0
Details
npm
2026-08-19 16:47:48 +00:00
207
UNLICENSED
latest
8.4 KiB
Assets (1)
link-1.0.0.tgz 8.4 KiB
Versions (1) View all
1.0.0 2026-08-19