Architecture du backend

Stack technique

  • Runtime : Node.js 20 + TypeScript

  • Framework : Express

  • Base de données : MongoDB (Mongoose)

  • Validation : Zod

  • Tests : Jest

Organisation du code

src/
├── config/          # configuration (env, base de données)
├── middlewares/     # auth, tenant, gestion des erreurs
├── shared/
│   ├── clients/
│   │   └── tecdoc/  # TecDocClient générique (véhicules + articles)
│   ├── models/      # modèles Mongoose partagés
│   └── types/       # interfaces TypeScript partagées
├── client-app/
│   ├── articles/    # CRUD articles + recherche directe
│   ├── search/      # moteur de découverte (voir ci-dessous)
│   ├── vehicles/    # véhicules (utilise TecDocClient via shared)
│   └── ...          # autres modules (prices, stocks, brands…)
├── admin-app/       # routes et contrôleurs côté admin
├── types/           # types TypeScript globaux
├── utils/           # fonctions utilitaires
└── scripts/         # scripts de maintenance et migration

Le module search est un moteur de découverte général, séparé du CRUD articles. Il s’appuie sur la recherche directe existante (ArticleService.searchArticles) et l’enrichit via des résolveurs indépendants.

src/client-app/search/
├── search.routes.ts              # agrégateur de routes (préfixe /api/search)
└── articles/
    ├── article-discovery.service.ts  # orchestration des résolveurs
    ├── article-discovery.controller.ts
    ├── article-discovery.routes.ts   # GET /articles/discover
    ├── article-discovery.schema.ts   # validation Zod
    ├── article-discovery.types.ts
    └── resolvers/
        ├── resolver.interface.ts     # contrat ISearchResolver
        ├── oem.resolver.ts           # via article_relations (oem, replaces, replaced_by)
        ├── internal.resolver.ts      # via article_relations (cross, complementary)
        └── tecdoc.resolver.ts        # via API TecDoc + article_aliases

Architecture des résolveurs

Chaque résolveur implémente ISearchResolver :

interface ISearchResolver {
  name: 'oem' | 'internal' | 'tecdoc';
  resolve(articleIds: string[], companyId: string): Promise<ResolvedRef[]>;
}

Le DiscoveryService appelle les résolveurs demandés en Promise.all, déduplique les résultats, puis enrichit les nouveaux articles avec prix et stock.

Pour ajouter un nouveau résolveur (ex. VanHeck), il suffit d’implémenter ISearchResolver et de l’enregistrer dans ArticleDiscoveryService.resolvers.

Client TecDoc

Le TecDocClient est partagé dans src/shared/clients/tecdoc/tecdoc.client.ts. Il expose des méthodes pour :

  • Véhicules : getManufacturers, getModelSeries, getVariants, getVehicleByKType

  • Articles : getArticles — recherche par référence avec refs OEM, remplacements et remplacés-par

Multi-tenancy

Chaque requête est associée à un tenantId injecté par le middleware tenant. Toutes les collections MongoDB incluent un champ tenantId indexé. L’isolation des données entre tenants est garantie au niveau de chaque requête base de données.

Gestion des erreurs

Les erreurs métier sont centralisées dans un catalogue d’erreurs (shared/errors). Le middleware d’erreur Express intercepte et formate toutes les réponses d’erreur.