Créez votre propre API à l'aide de ces technologies Web populaires.

GraphQL et NestJS forment un excellent partenariat, vous offrant une base solide pour vos API et un cadre facile à utiliser pour créer des applications Web évolutives. La combinaison est parfaite pour créer des applications prêtes pour la production, et les deux sont des outils très pertinents dans l'écosystème technologique d'aujourd'hui.

Découvrez comment créer une API à l'aide des deux produits.

Qu'est-ce que GraphQL?

GraphQL est un langage de requête et de manipulation de données vous pouvez utiliser pour créer des API de manière plus précise et concise. GraphQL fournit une description complète et adéquate des données existant dans une API et donne au client le pouvoir d'obtenir les données exactes nécessaires.

GraphQL fournit de nombreuses fonctionnalités qui manquent aux API REST, allant des requêtes de données précises à de meilleurs outils de développement, comme le graphique éditeur. Il vous permet également d'interroger plusieurs ressources via une seule requête.

instagram viewer

Qu'est-ce que NestJS?

NestJS est un framework Node.js progressif que vous pouvez utiliser pour créer des applications côté serveur évolutives et efficaces. NestJS fournit de nombreux plugins, ainsi que des outils pour un développement rapide et facile, notamment la prise en charge de GraphQL, GRPC, WebSockets, etc.

NestJS est bien connu dans l'écosystème pour sa structure de projet optimisée utilisant des modules, des contrôleurs, des services et des schémas. Sa CLI intégrée vous permet de créer une architecture d'API structurée. Vous pouvez utiliser principes d'injection de dépendance pour contrôler la façon dont les parties d'une application communiquent entre elles.

Implémentation de GraphQL avec NestJS et MongoDB

Avant de créer une API avec NestJS et GraphQL, vous devez disposer des bonnes dépendances. Vous avez besoin pour installer Node.js et NestJS, que vous pouvez installer en exécutant npm i -g @nestjs/cli.

L'exemple qui suit est une application simple qui stocke des informations sur les livres. Exécutez la commande suivante dans votre terminal pour créer une nouvelle application NestJS :

nid nouveau 

Accédez au répertoire de l'application générée () et installez ses dépendances avec la commande suivante :

$ npm install --save @nestjs/config @nestjs/graphql graphql-tools graphql \
 @nestjs/apollo apollo-server-express @nestjs/mongoose @types/graphql

Il existe deux approches principales pour créer des API GraphQL, à savoir :

  1. Approche schématique : où vous décrivez l'API dans des fichiers de définition de schéma ou SDL, et NestJS génère des définitions Typescript basées sur eux.
  2. Approche code d'abord : où vous définissez des requêtes, des mutations et d'autres fonctionnalités GraphQL à l'aide de classes et de décorateurs Typescript, et NestJS génère des fichiers SDL basés sur eux.

L'exemple suivant décrit comment utiliser une approche code-first.

Tout d'abord, vous devez initialiser GraphQL dans votre Module d'application et connectez-le à une base de données MongoDB:

// app.module.ts
importer { Module } depuis'@nestjs/commun';
importer { GraphQLModule comme NestGraphQLModule } depuis'@nestjs/graphql';
importer { ApolloDriver, ApolloDriverConfig } depuis'@nestjs/apollo';
importer { rejoindre } depuis'chemin';
importer {Module Mongoose} depuis'@nestjs/mangouste';
importer { Contrôleur d'application } depuis'./app.controller';
importer { AppService } depuis'./app.service';
importer { ConfigModule, ConfigService } depuis'@nestjs/config';
importer mongodbConfig depuis'./config/mongodb.config';

@Module({
importations: [
ConfigModule.forRoot({
charger: [mongodbConfig],
estGlobal: vrai
}),
NestGraphQLModule.forRootAsync({
pilote: ApolloDriver,
injecter: [ConfigService],
useFactory: asynchrone (configService: ConfigService) => ({
autoSchemaFile: jointure (process.cwd(), 'src/schema.gql'),
installSubscriptionHandler: vrai,
sortSchema: vrai,
Cour de récréation: vrai,
débogage: configService.get<booléen>("DÉBOGUER"),
téléchargements: FAUX,
}),
}),
MongooseModule.forRootAsync({
injecter: [ConfigService],
useFactory: asynchrone (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
],
contrôleurs: [AppController],
fournisseurs: [AppService],
})

exporterclasse Module d'application {}

Ce module importe le GraphQLModule depuis @nestjs/graphql et le Module Mangouste depuis @nestjs/mangouste qui aide à se connecter à MongoDB. Le autoSchemaFileautoSchemaFile La propriété spécifie l'emplacement du fichier de schéma généré et la propriété triSchéma La propriété garantit qu'elle ordonne les champs par ordre alphabétique.

Voici ce que votre MongoDB configuration le fichier devrait ressembler à :

importer { enregistrerAs } depuis'@nestjs/config';

/**
 * Configuration de la connexion à la base de données Mongo
 */
exporterdéfaut s'inscrireAs('mongodb', () => {
constante {
MONGO_URI
} = processus.env ;

retour {
uri: `${MONGO_URI}`,
};
});

Définition du schéma GraphQL

Après avoir configuré les connexions GraphQL et MongoDB, vous devez définir des requêtes et des mutations GraphQL pour générer un schéma (schéma.gql) déposer.

Rédaction de requêtes

Dans le approche code-first, vous créez un modèle à l'aide de Type d'objet décorateur. Vous transformerez ultérieurement ce modèle en un type GraphQL.

Par exemple:

// livre.modèle.ts
importer { Champ, Type d'objet } depuis'@nestjs/graphql';
importer { Prop, Schema, SchemaFactory } depuis'@nestjs/mangouste';
importer { Document } depuis'mangouste';

exportertaper BookDocument = Livre & Document ;

@Type d'objet()
@Schéma()
exporterclasse Livre {
@Champ()
titre: chaîne;

@Champ()
auteur: chaîne;

@Champ()
date de publication: booléen;
}

exporterconstante BookSchema = SchemaFactory.createForClass (Livre);

GraphQL, par défaut, ne peut pas utiliser les schémas créés. Pour les rendre fonctionnels, vous avez besoin d'un service de résolution contenant les fonctions d'exécution des types GraphQL. Vous pouvez le faire avec le Résolveur décorateur.

// livres.résolveur.ts
importer { Résolveur, Requête, Mutation, Args, ID } depuis'@nestjs/graphql';
importer { Livre } depuis'./book.model';
importer { BookService } depuis'./livres.service';

@Résolveur(() => Livre)
exporterclasse BookResolver {
constructeur(privé service de livre en lecture seule: service de livre) { }

@Mettre en doute(() => [Livre])
asynchrone livres(): Promesse {
retource.bookService.findAll();
}

@Mettre en doute(() => Livre)
asynchrone livre(@Args('identifiant', { taper: () => Je l'ai fait: chaîne): Promesse {
retource.bookService.findOne (identifiant) ;
}
}

Vous pouvez mettre en œuvre le RéserverService, importé ci-dessus, comme suit :

// livres.service.ts
importer { Injectables } depuis'@nestjs/commun';
importer { InjectModel } depuis'@nestjs/mangouste';
importer { Modèle } depuis'mangouste';
importer { Livre, LivreDocument } depuis'./book.model';

@Injectable()
exporterclasse Service de réservation {
constructeur(@InjectModel(Livre.nom) privé livreModèle: Modèle) { }

asynchrone Trouver tout(): Promesse {
retource.bookModel.find().exec();
}

asynchrone findOne (identifiant: chaîne): Promesse {
retource.bookModel.findById (id).exec();
}
}

Vous devez également ajouter le BookResolver à la liste des fournisseurs dans livres.module.ts.

importer { Module } depuis"@nestjs/commun";
importer {Module Mongoose} depuis"@nestjs/mangouste";
importer { BookService } depuis'./livres.service';
importer { BookResolver } depuis'./books.résolveur';
importer { Livre, LivreSchéma } depuis'./book.model';

@Module({
fournisseurs: [
BookService,
BookResolver
],
importe: [MongooseModule.forFeature([
{
nom: nom.du.livre,
schéma: BookSchema,
},
]),
],
})

exporterclasse LivresModule {}

Travailler avec des mutations

Lorsque vous utilisez une requête pour récupérer des données dans GraphQL, des mutations créent ou mettent à jour des données dans la base de données. Pour créer des mutations, vous devez accepter les données des utilisateurs. Le Type d'entrée décorateur, qui transforme une classe en un type d'entrée GraphQL, est utile ici.

// livre.entrée.ts
importer { Type d'entrée, Champ } depuis'@nestjs/graphql';

@Type d'entrée()
exporterclasse BookInput {
@Champ()
titre: chaîne;

@Champ()
auteur: chaîne;

@Champ()
date de publication: booléen
}

Vous pouvez maintenant mettre à jour livres.resolver.ts ressembler à ceci :

importer { Résolveur, Requête, Mutation, Args, ID } depuis'@nestjs/graphql';
importer { Livre } depuis'./book.model';
importer { BookService } depuis'./livres.service';
importer { BookInput } depuis'./livre.entrée';

@Résolveur(() => Livre)
exporterclasse BookResolver {
constructeur(privé service de livre en lecture seule: service de livre) { }

@Mutation(() => Livre)
asynchrone créerLivre(@Args('saisir') entrée: BookInput): Promesse {
retource.bookService.create (entrée) ;
}

@Mutation(() => Livre)
asynchrone mise à jourLivre(
@Args('identifiant', { taper: () => Je l'ai fait: chaîne,
@Args('saisir') entrée: BookInput,
): Promesse {
retource.bookService.update (identifiant, entrée);
}

@Mutation(() => Livre)
asynchrone supprimerLivre(@Args('identifiant', { taper: () => Je l'ai fait: chaîne): Promesse {
retource.bookService.delete (identifiant);
}
}

Et livres.service.ts comme ça:

importer { Injectables } depuis'@nestjs/commun';
importer { InjectModel } depuis'@nestjs/mangouste';
importer { Modèle } depuis'mangouste';
importer { Livre, LivreDocument } depuis'./book.model';

@Injectable()
exporterclasse Service de réservation {
constructeur(@InjectModel(Livre.nom) privé livreModèle: Modèle) { }

asynchrone créer (livre: Livre): Promesse {
constante nouveauLivre = nouveauce.bookModel (livre);
retour newBook.save();
}

asynchrone mise à jour (identifiant: chaîne, livre livre): Promesse {
retource.bookModel.findByIdAndUpdate (id, livre, { nouveau: vrai }).exec();
}

asynchronesupprimer(identifiant: chaîne): Promesse {
retource.bookModel.findByIdAndDelete (id).exec();
}
}

Le @Mutation décorateur marque une fonction comme un type de mutation et le @Args le décorateur récupère toutes les entrées transmises à la fonction.

Enfin, vous devez importer le Module Livres dans Module d'application pour le rendre fonctionnel. Vous devez également passer le Module Livres pour pourRootAsync comme vu ci-dessous.

importer { Module Livres } depuis'./livres/livres.module';
/**
 * autres importations
*/

@Module({
importations: [
ConfigModule.forRoot({
charger: [mongodbConfig],
estGlobal: vrai
}),
NestGraphQLModule.forRootAsync({
pilote: ApolloDriver,
injecter: [ConfigService],
useFactory: asynchrone (configService: ConfigService) => ({
autoSchemaFile: jointure (process.cwd(), 'src/schema.gql'),
installSubscriptionHandler: vrai,
sortSchema: vrai,
Cour de récréation: vrai,
débogage: configService.get<booléen>("DÉBOGUER"),
téléchargements: FAUX,
}),
}),
MongooseModule.forRootAsync({
injecter: [ConfigService],
useFactory: asynchrone (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
Module Livres,
],
contrôleurs: [AppController],
fournisseurs: [AppService],
})

exporterclasse Module d'application {}

Vous pouvez tester le code en exécutant démarrage de l'exécution npm: dev dans votre terminal, et votre application devrait démarrer avec succès sur le port 3000.

Ouvrir hôte local: 3000/graphql dans votre navigateur pour afficher Graphique interface où vous pouvez tester les requêtes et les mutations. Voici un exemple qui montre une requête :

Et voici un exemple de mutation :

Créez des API efficaces avec NestJS et GraphQL

Construire une API GraphQL dans NestJS avec MongoDB à l'aide de Mongoose implique de définir un schéma pour l'API GraphQL, un schéma pour le modèle Mongoose, un service pour interagir avec la base de données et un résolveur pour mapper les opérations GraphQL au service méthodes.

NestJS dispose de fonctionnalités intégrées pour créer des API, notamment des décorateurs pour définir les itinéraires, des gardes pour les protéger et des intergiciels pour gérer les demandes et les réponses. Il prend également en charge d'autres bases de données telles que PostgreSQL, MySQL et SQLite, ainsi que d'autres bibliothèques GraphQL telles qu'Apollo et TypeGraphQL.