Bygg ditt eget API med dessa populära webbteknologier.
GraphQL och NestJS är ett utmärkt partnerskap som ger dig en solid grund för dina API: er och ett lättanvänt ramverk för att bygga skalbara webbapplikationer. Kombinationen är perfekt för att bygga produktionsklara appar, och båda är mycket relevanta verktyg i dagens tekniska ekosystem.
Ta reda på mer om hur du kan bygga ett API med båda produkterna.
Vad är GraphQL?
GraphQL är ett dataförfrågnings- och manipulationsspråk du kan använda för att bygga API: er på ett mer exakt och kortfattat sätt. GraphQL ger en fullständig och adekvat beskrivning av data som finns i ett API och ger kraft till klienten att få exakt den data som behövs.
GraphQL tillhandahåller många funktioner som REST API: er saknar, allt från exakta datafrågor till bättre utvecklarverktyg, som grafiql redaktör. Det låter dig också fråga efter flera resurser via en enda begäran.
Vad är NestJS?
NestJS är ett progressivt Node.js-ramverk som du kan använda för att bygga skalbara och effektiva applikationer på serversidan. NestJS tillhandahåller många plugins, tillsammans med verktyg för snabb och enkel utveckling inklusive GraphQL-stöd, GRPC, WebSockets, etc.
NestJS är välkänt i ekosystemet för sin optimerade projektstruktur med hjälp av moduler, kontroller, tjänster och scheman. Dess inbyggda CLI låter dig skapa en strukturerad API-arkitektur. Du kan använda principer för beroendeinjektion att styra hur delarna av en applikation kommunicerar med varandra.
Implementering av GraphQL med NestJS och MongoDB
Innan du bygger ett API med NestJS och GraphQL måste du ha rätt beroenden tillgängliga. Du behöver för att installera Node.js och NestJS, som du kan installera genom att köra npm i -g @nestjs/cli.
Exemplet som följer är en enkel app som lagrar information om böcker. Kör följande kommando i din terminal för att skapa en ny NestJS-applikation:
bo nytt
Navigera till det genererade programmets katalog () och installera dess beroenden med följande kommando:
$ npm install --save @nestjs/config @nestjs/graphql graphql-tools graphql \
@nestjs/apollo apollo-server-express @nestjs/mongoose @types/graphql
Det finns två huvudsakliga metoder för att bygga GraphQL API: er, nämligen:
- Schema-första tillvägagångssätt: där du beskriver API: et i schemadefinitionsfiler eller SDL, och NestJS genererar Typescript-definitioner baserat på dem.
- Kod-första tillvägagångssätt: där du definierar frågor, mutationer och andra GraphQL-funktioner med hjälp av Typescript-klasser och dekoratörer, och NestJS genererar SDL-filer baserat på dem.
Följande exempel beskriver hur man använder en kod-först-metod.
Först måste du initiera GraphQL i din AppModul och anslut den till en MongoDB-databas:
// app.module.ts
importera { Modul } från'@nestjs/common';
importera { GraphQLModule som NestGraphQLModule } från'@nestjs/graphql';
importera { ApolloDriver, ApolloDriverConfig } från'@nestjs/apollo';
importera { Ansluta sig } från'väg';
importera { MongooseModule } från'@nestjs/mongoose';
importera { AppController } från'./app.controller';
importera { AppService } från'./app.service';
importera { ConfigModule, ConfigService } från'@nestjs/config';
importera mongodbConfig från'./config/mongodb.config';@Modul({
importer: [
ConfigModule.forRoot({
ladda: [mongodbConfig],
isGlobal: Sann
}),
NestGraphQLModule.forRootAsync({
förare: ApolloDriver,
injicera: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: Sann,
sortSchema: Sann,
lekplats: Sann,
debug: configService.get<booleskt>("DEBUG"),
uppladdningar: falsk,
}),
}),
MongooseModule.forRootAsync({
injicera: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
],
kontroller: [AppController],
leverantörer: [AppService],
})
exporteraklass AppModule {}
Denna modul importerar GraphQLModule från @nestjs/graphql och den MongooseModule från @nestjs/mongoose som hjälper till att ansluta till MongoDB. De autoSchemaFile egenskapen anger platsen för den genererade schemafilen och sortSchema egenskapen ser till att den ordnar fälten alfabetiskt.
Här är vad din MongoDB config filen ska se ut så här:
importera { registerAs } från'@nestjs/config';
/**
* Mongo databas anslutningskonfiguration
*/
exporterastandard registerAs('mongodb', () => {
konst {
MONGO_URI
} = process.env;
lämna tillbaka {
uri: `${MONGO_URI}`,
};
});
Definiera GraphQL-schemat
Efter att ha ställt in GraphQL- och MongoDB-anslutningarna bör du definiera GraphQL-frågor och mutationer för att generera ett schema (schema.gql) fil.
Skriva frågor
I den kod-första tillvägagångssättskapar du en modell med hjälp av ObjectType dekoratör. Du kommer senare att omvandla denna modell till en GraphQL-typ.
Till exempel:
// book.model.ts
importera { Field, ObjectType } från'@nestjs/graphql';
importera { Prop, Schema, SchemaFactory } från'@nestjs/mongoose';
importera { Dokument } från'mungo';exporteratyp BookDocument = Bok & Dokument;
@ObjectType()
@Schema()
exporteraklass Bok {
@Fält()
titel: sträng;@Fält()
författare: sträng;@Fält()
publiceringsdatum: booleskt;
}
exporterakonst BookSchema = SchemaFactory.createForClass (bok);
GraphQL kan som standard inte använda de skapade schemana. För att göra dem funktionella behöver du en resolvertjänst som innehåller funktionerna för att exekvera GraphQL-typerna. Du kan göra det med Upplösare dekoratör.
// books.resolver.ts
importera { Resolver, Query, Mutation, Args, ID } från'@nestjs/graphql';
importera { Bok } från'./book.model';
importera { BookService } från'./books.service';@Resolver(() => Bok)
exporteraklass BookResolver {
konstruktör(privat skrivskyddad bookService: BookService) { }@Fråga(() => [Bok])
asynkron böcker(): Löfte{
lämna tillbakadetta.bookService.findAll();
}
@Fråga(() => Bok)
asynkron bok(@Args('id', { typ: () => Jag gjorde: sträng): Löfte{
lämna tillbakadetta.bookService.findOne (id);
}
}
Du kan implementera Boktjänst,importerat ovan, enligt följande:
// books.service.ts
importera { Injicerbar } från'@nestjs/common';
importera { InjectModel } från'@nestjs/mongoose';
importera { Modell } från'mungo';
importera { Bok, bokdokument } från'./book.model';@Injicerbar()
exporteraklass BookService {
konstruktör(@InjectModel(Book.name) privat bokModell: Modell) { }asynkron hitta alla(): Löfte
{
lämna tillbakadetta.bookModel.find().exec();
}
asynkron findOne (id: sträng): Löfte
{
lämna tillbakadetta.bookModel.findById (id).exec();
}
}
Du måste också lägga till BookResolver i listan över leverantörer i books.modul.ts.
importera { Modul } från"@nestjs/common";
importera { MongooseModule } från"@nestjs/mongoose";
importera { BookService } från'./books.service';
importera { BookResolver } från'./books.resolver';
importera { Bok, BookSchema } från'./book.model';@Modul({
leverantörer: [
Boktjänst,
BookResolver
],
importer: [MongooseModule.forFeature([
{
namn: Bok.namn,
schema: BookSchema,
},
]),
],
})
exporteraklass BooksModule {}
Arbeta med mutationer
Medan du använder en fråga för att hämta data i GraphQL skapar eller uppdaterar mutationer data i databasen. För att skapa mutationer måste du acceptera data från användare. De InputType decorator, som förvandlar en klass till en GraphQL-inmatningstyp, kommer väl till pass här.
// book.input.ts
importera { InputType, Field } från'@nestjs/graphql';@InputType()
exporteraklass BookInput {
@Fält()
titel: sträng;@Fält()
författare: sträng;
@Fält()
publiceringsdatum: booleskt
}
Du kan nu uppdatera books.resolver.ts att se ut så här:
importera { Resolver, Query, Mutation, Args, ID } från'@nestjs/graphql';
importera { Bok } från'./book.model';
importera { BookService } från'./books.service';
importera { BookInput } från'./book.input';@Resolver(() => Bok)
exporteraklass BookResolver {
konstruktör(privat skrivskyddad bookService: BookService) { }@Mutation(() => Bok)
asynkron skapa Bok(@Args('inmatning') input: BookInput): Löfte{
lämna tillbakadetta.bookService.create (ingång);
}@Mutation(() => Bok)
asynkron uppdatera Bok(
@Args('id', { typ: () => Jag gjorde: sträng,
@Args('inmatning') input: BookInput,
): Löfte{
lämna tillbakadetta.bookService.update (id, input);
}
@Mutation(() => Bok)
asynkron radera Bok(@Args('id', { typ: () => Jag gjorde: sträng): Löfte{
lämna tillbakadetta.bookService.delete (id);
}
}
Och books.service.ts så här:
importera { Injicerbar } från'@nestjs/common';
importera { InjectModel } från'@nestjs/mongoose';
importera { Modell } från'mungo';
importera { Bok, bokdokument } från'./book.model';@Injicerbar()
exporteraklass BookService {
konstruktör(@InjectModel(Book.name) privat bokModell: Modell) { }asynkron skapa (bok: Bok): Löfte
{
konst nybok = nydetta.bookModel (bok);
lämna tillbaka newBook.save();
}asynkron uppdatering (id: sträng, bok: Bok): Löfte
{
lämna tillbakadetta.bookModel.findByIdAndUpdate (id, bok, { ny: Sann }).exec();
}
asynkronradera(id: sträng): Löfte
{
lämna tillbakadetta.bookModel.findByIdAndDelete (id).exec();
}
}
De @Mutation dekoratör markerar en funktion som en mutationstyp och den @Args decorator tar tag i alla ingångar som skickas till funktionen.
Slutligen bör du importera BooksModule in i AppModul för att göra det funktionellt. Du bör också klara BooksModule till för RootAsync som ses nedan.
importera { BooksModule } från'./books/books.module';
/**
* annan import
*/@Modul({
importer: [
ConfigModule.forRoot({
ladda: [mongodbConfig],
isGlobal: Sann
}),
NestGraphQLModule.forRootAsync({
förare: ApolloDriver,
injicera: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: Sann,
sortSchema: Sann,
lekplats: Sann,
debug: configService.get<booleskt>("DEBUG"),
uppladdningar: falsk,
}),
}),
MongooseModule.forRootAsync({
injicera: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
BooksModule,
],
kontroller: [AppController],
leverantörer: [AppService],
})
exporteraklass AppModule {}
Du kan testa koden genom att köra npm körstart: dev i din terminal, och din applikation bör starta framgångsrikt på port 3000.
Öppen localhost: 3000/graphql i din webbläsare för att visa Graphiql gränssnitt där du kan testa frågor och mutationer. Här är ett exempel som visar en fråga:
Och här är ett exempel på en mutation:
Bygg effektiva API: er med NestJS och GraphQL
Att bygga ett GraphQL API i NestJS med MongoDB med Mongoose innebär att definiera ett schema för GraphQL API, ett schema för Mongoose-modellen, en tjänst för att interagera med databasen och en resolver för att mappa GraphQL-operationer till tjänst metoder.
NestJS har inbyggd funktionalitet för att bygga API: er, inklusive dekoratörer för att definiera rutter, vakter för att skydda dem och mellanprogram för hantering av förfrågningar och svar. Den stöder också andra databaser som PostgreSQL, MySQL och SQLite, såväl som andra GraphQL-bibliotek som Apollo och TypeGraphQL.