Je crée une API pour plusieurs clients. Les points de terminaison de base comme /users
sont utilisés par chaque client, mais certains points de terminaison reposent sur une personnalisation individuelle. Il se peut donc que l' utilisateur A veuille un point de terminaison spécial /groups
et aucun autre client n'aura cette fonctionnalité. Tout comme un sidenote , chaque client utiliserait également son propre schéma de base de données en raison de ces fonctionnalités supplémentaires.
J'utilise personnellement NestJs (Express sous le capot). Donc, le app.module
enregistre actuellement tous mes modules de base (avec leurs propres points de terminaison, etc.)
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module'; // core module
@Module({
imports: [UsersModule]
})
export class AppModule {}
Je pense que ce problème n'est pas lié aux NestJ, alors comment gérez-vous cela en théorie?
J'ai essentiellement besoin d'une infrastructure capable de fournir un système de base. Il n'y a plus de noeuds finaux principaux car chaque extension est unique et plusieurs /users
implémentations pourraient être possibles. Lors du développement d'une nouvelle fonctionnalité, l'application principale ne doit pas être touchée. Les extensions doivent s'intégrer ou doivent être intégrées au démarrage. Le système principal est livré sans point d'extrémité mais sera étendu à partir de ces fichiers externes.
Quelques idées me viennent à l'esprit
Première approche:
Chaque extension représente un nouveau référentiel. Définissez un chemin d'accès à un dossier externe personnalisé contenant tous ces projets d'extension. Ce répertoire personnalisé contiendrait un dossier groups
avec ungroups.module
import { Module } from '@nestjs/common';
import { GroupsController } from './groups.controller';
@Module({
controllers: [GroupsController],
})
export class GroupsModule {}
Mon API peut parcourir ce répertoire et essayer d'importer chaque fichier de module.
avantages:
- Le code personnalisé est conservé à l'écart du référentiel principal
les inconvénients:
NestJs utilise Typescript, je dois donc d'abord compiler le code. Comment gérer la version d'API et les versions à partir des applications personnalisées? (Système plug and play)
Les extensions personnalisées sont très lâches car elles ne contiennent que des fichiers dactylographiés. Du fait qu'ils n'ont pas accès au répertoire node_modules de l'API, mon éditeur me montrera des erreurs car il ne peut pas résoudre les dépendances de packages externes.
Certaines extensions peuvent extraire des données d'une autre extension. Peut-être que le service des groupes doit accéder au service des utilisateurs. Les choses pourraient devenir délicates ici.
Deuxième approche: conserver chaque extension dans un sous-dossier du dossier src de l'API. Mais ajoutez ce sous-dossier au fichier .gitignore. Vous pouvez maintenant conserver vos extensions dans l'API.
avantages:
Votre éditeur est capable de résoudre les dépendances
Avant de déployer votre code, vous pouvez exécuter la commande build et disposer d'une seule distribution
Vous pouvez accéder facilement à d'autres services (
/groups
besoin de trouver un utilisateur par identifiant)
les inconvénients:
- Lors du développement, vous devez copier vos fichiers de référentiel dans ce sous-dossier. Après avoir changé quelque chose, vous devez recopier ces fichiers et remplacer vos fichiers de référentiel par ceux mis à jour.
Troisième approche:
Dans un dossier personnalisé externe, toutes les extensions sont des API autonomes à part entière. Votre API principale fournirait simplement les éléments d'authentification et pourrait agir comme un proxy pour rediriger les demandes entrantes vers l'API cible.
avantages:
- De nouvelles extensions peuvent être développées et testées facilement
les inconvénients:
Le déploiement sera délicat. Vous aurez une API principale et n API d'extension démarrant leur propre processus et écoutant un port.
Le système proxy pourrait être délicat. Si le client demande
/users
au proxy de savoir quelle API d'extension écoute pour ce point de terminaison, appelle cette API et retransmet cette réponse au client.Pour protéger les API d'extension (l'authentification est gérée par l'API principale), le proxy doit partager un secret avec ces API. L'API d'extension ne transmettra donc les demandes entrantes que si le secret correspondant est fourni par le proxy.
Quatrième approche:
Les microservices pourraient vous aider. J'ai pris un guide d'ici https://docs.nestjs.com/microservices/basics
Je pourrais avoir un microservice pour la gestion des utilisateurs, la gestion de groupe, etc. et consommer ces services en créant un petit api / passerelle / proxy qui appelle ces microservices.
avantages:
De nouvelles extensions peuvent être développées et testées facilement
Préoccupations séparées
les inconvénients:
Le déploiement sera délicat. Vous disposerez d'une API principale et de n microservices démarrant leur propre processus et écoutant un port.
Il semble que je devrais créer une nouvelle API de passerelle pour chaque client si je veux la personnaliser. Au lieu d'étendre une application, je devrais donc créer à chaque fois une API de consommation personnalisée. Cela ne résoudrait pas le problème.
Pour protéger les API d'extension (l'authentification est gérée par l'API principale), le proxy doit partager un secret avec ces API. L'API d'extension ne transmettra donc les demandes entrantes que si le secret correspondant est fourni par le proxy.