Bygg ditt eget API ved å bruke disse populære nettteknologiene.

GraphQL og NestJS utgjør et utmerket partnerskap, og gir deg et solid grunnlag for API-ene dine og et brukervennlig rammeverk for å bygge skalerbare webapplikasjoner. Kombinasjonen er perfekt for å bygge produksjonsklare apper, og begge er svært relevante verktøy i dagens teknologiøkosystem.

Finn ut mer om hvordan du kan bygge et API ved å bruke begge produktene.

Hva er GraphQL?

GraphQL er et dataspørrings- og manipulasjonsspråk du kan bruke til å bygge API-er på en mer presis og kortfattet måte. GraphQL gir en fullstendig og adekvat beskrivelse av dataene som finnes i en API og gir kraft til klienten for å få de nøyaktige dataene som trengs.

GraphQL gir mange funksjoner som REST API-er mangler, alt fra presise dataspørringer til bedre utviklerverktøy, som graphiql redaktør. Den lar deg også spørre etter flere ressurser via en enkelt forespørsel.

Hva er NestJS?

NestJS er et progressivt Node.js-rammeverk du kan bruke til å bygge skalerbare og effektive applikasjoner på serversiden. NestJS tilbyr mange plugins, sammen med verktøy for rask og enkel utvikling, inkludert GraphQL-støtte, GRPC, WebSockets, etc.

instagram viewer

NestJS er velkjent i økosystemet for sin optimaliserte prosjektstruktur ved bruk av moduler, kontrollere, tjenester og skjemaer. Den innebygde CLI lar deg lage en strukturert API-arkitektur. Du kan bruke avhengighetsinjeksjonsprinsipper å kontrollere hvordan delene av en applikasjon kommuniserer med hverandre.

Implementering av GraphQL med NestJS og MongoDB

Før du bygger et API med NestJS og GraphQL, må du ha de riktige avhengighetene tilgjengelig. Du trenger for å installere Node.js og NestJS, som du kan installere ved å kjøre npm i -g @nestjs/cli.

Eksempelet som følger er en enkel app som lagrer informasjon om bøker. Kjør følgende kommando i terminalen din for å lage en ny NestJS-applikasjon:

reir ny 

Naviger til den genererte applikasjonens katalog () og installer avhengighetene med følgende kommando:

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

Det er to hovedtilnærminger for å bygge GraphQL APIer, nemlig:

  1. Skjema-første tilnærming: hvor du beskriver API i skjemadefinisjonsfiler eller SDL, og NestJS genererer Typescript-definisjoner basert på dem.
  2. Kode-først tilnærming: hvor du definerer spørringer, mutasjoner og andre GraphQL-funksjoner ved å bruke Typescript-klasser og dekoratorer, og NestJS genererer SDL-filer basert på dem.

Følgende eksempel beskriver hvordan du bruker en kode-først-tilnærming.

Først må du initialisere GraphQL i din AppModule og koble den til en MongoDB-database:

// app.module.ts
import { Modul } fra'@nestjs/common';
import { GraphQLModule som NestGraphQLModule } fra'@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } fra'@nestjs/apollo';
import { bli med } fra'sti';
import { MongooseModule } fra'@nestjs/mongoose';
import { AppController } fra'./app.controller';
import { AppService } fra'./app.service';
import { ConfigModule, ConfigService } fra'@nestjs/config';
import mongodbConfig fra'./config/mongodb.config';

@Modul({
importerer: [
ConfigModule.forRoot({
last: [mongodbConfig],
isGlobal: ekte
}),
NestGraphQLModule.forRootAsync({
sjåfør: ApolloDriver,
inject: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: ekte,
sortSchema: ekte,
lekeplass: ekte,
debug: configService.get<boolsk>("DEBUG"),
opplastinger: falsk,
}),
}),
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
],
kontrollere: [AppController],
leverandører: [AppService],
})

eksportklasse AppModule {}

Denne modulen importerer GraphQLModule fra @nestjs/graphql og MongooseModule fra @nestjs/mongoose som hjelper til med å koble til MongoDB. De autoSchemaFile egenskapen angir plasseringen av den genererte skjemafilen, og sortSchema egenskap sikrer at den sorterer feltene alfabetisk.

Her er hva din MongoDB konfig filen skal se slik ut:

import { registerAs } fra'@nestjs/config';

/**
 * Mongo-databasetilkoblingskonfigurasjon
 */
eksportmisligholde registerAs('mongodb', () => {
konst {
MONGO_URI
} = prosess.env;

komme tilbake {
uri: `${MONGO_URI}`,
};
});

Definere GraphQL-skjemaet

Etter å ha satt opp GraphQL- og MongoDB-forbindelsene, bør du definere GraphQL-spørringer og mutasjoner for å generere et skjema (schema.gql) fil.

Skrive spørsmål

I kode-første tilnærming, lager du en modell ved å bruke Objekttype dekoratør. Du vil senere transformere denne modellen til en GraphQL-type.

For eksempel:

// book.model.ts
import { Field, ObjectType } fra'@nestjs/graphql';
import { Prop, Schema, SchemaFactory } fra'@nestjs/mongoose';
import { Dokument } fra"mangus";

eksporttype BookDocument = Bok og dokument;

@ObjectType()
@Skjema()
eksportklasse Bestill {
@Felt()
tittel: streng;

@Felt()
forfatter: streng;

@Felt()
publisert dato: boolsk;
}

eksportkonst BookSchema = SchemaFactory.createForClass (Bok);

GraphQL kan som standard ikke bruke de opprettede skjemaene. For å gjøre dem funksjonelle trenger du en resolver-tjeneste som inneholder funksjonene for å utføre GraphQL-typene. Du kan gjøre det med Løser dekoratør.

// books.resolver.ts
import { Resolver, Query, Mutation, Args, ID } fra'@nestjs/graphql';
import { Bok } fra'./book.model';
import { BookService } fra'./books.service';

@Resolver(() => Bok)
eksportklasse BookResolver {
konstruktør(privat readonly bookService: BookService) { }

@Spørsmål(() => [Bok])
asynkron bøker(): Love {
komme tilbakedette.bookService.findAll();
}

@Spørsmål(() => Bok)
asynkron bok(@Args('id', { type: () => Jeg gjorde: streng): Love {
komme tilbakedette.bookService.findOne (id);
}
}

Du kan implementere BookService,importert ovenfor, som følger:

// books.service.ts
import { Injiserbar } fra'@nestjs/common';
import { InjectModel } fra'@nestjs/mongoose';
import { Modell } fra"mangus";
import { Bok, bokdokument } fra'./book.model';

@Injiserbar()
eksportklasse BookService {
konstruktør(@InjectModel(Book.name) privat bokModell: Modell) { }

asynkron finnAlle(): Love {
komme tilbakedette.bookModel.find().exec();
}

asynkron findOne (id: streng): Love {
komme tilbakedette.bookModel.findById (id).exec();
}
}

Du må også legge til BookResolver i listen over leverandører i books.module.ts.

import { Modul } fra"@nestjs/common";
import { MongooseModule } fra"@nestjs/mongoose";
import { BookService } fra'./books.service';
import { BookResolver } fra'./books.resolver';
import { Bok, BookSchema } fra'./book.model';

@Modul({
leverandører: [
Bokservice,
BookResolver
],
importerer: [MongooseModule.forFeature([
{
navn: Bok.navn,
skjema: BookSchema,
},
]),
],
})

eksportklasse BooksModule {}

Arbeid med mutasjoner

Mens du bruker en spørring for å hente data i GraphQL, oppretter eller oppdaterer mutasjoner data i databasen. For å lage mutasjoner må du godta data fra brukere. De InputType decorator, som gjør en klasse til en GraphQL-inndatatype, kommer godt med her.

// book.input.ts
import { InputType, Field } fra'@nestjs/graphql';

@InputType()
eksportklasse BookInput {
@Felt()
tittel: streng;

@Felt()
forfatter: streng;

@Felt()
publisert dato: boolsk
}

Du kan nå oppdatere books.resolver.ts å se slik ut:

import { Resolver, Query, Mutation, Args, ID } fra'@nestjs/graphql';
import { Bok } fra'./book.model';
import { BookService } fra'./books.service';
import { BookInput } fra'./book.input';

@Resolver(() => Bok)
eksportklasse BookResolver {
konstruktør(privat readonly bookService: BookService) { }

@Mutasjon(() => Bok)
asynkron lag bok(@Args('inngang') input: BookInput): Love {
komme tilbakedette.bookService.create (inndata);
}

@Mutasjon(() => Bok)
asynkron oppdater bok(
@Args('id', { type: () => Jeg gjorde: streng,
@Args('inngang') input: BookInput,
): Love {
komme tilbakedette.bookService.update (id, input);
}

@Mutasjon(() => Bok)
asynkron slettBok(@Args('id', { type: () => Jeg gjorde: streng): Love {
komme tilbakedette.bookService.delete (id);
}
}

Og books.service.ts som dette:

import { Injiserbar } fra'@nestjs/common';
import { InjectModel } fra'@nestjs/mongoose';
import { Modell } fra"mangus";
import { Bok, bokdokument } fra'./book.model';

@Injiserbar()
eksportklasse BookService {
konstruktør(@InjectModel(Book.name) privat bokModell: Modell) { }

asynkron opprette (bok: Bok): Love {
konst nybok = nydette.bookModel (bok);
komme tilbake newBook.save();
}

asynkron oppdatering (id: streng, bok: Bok): Love {
komme tilbakedette.bookModel.findByIdAndUpdate (id, bok, { ny: ekte }).exec();
}

asynkronslette(id: streng): Love {
komme tilbakedette.bookModel.findByIdAndDelete (id).exec();
}
}

De @Mutasjon dekorator markerer en funksjon som en mutasjonstype og den @Args decorator tar tak i alle innganger som sendes inn i funksjonen.

Til slutt bør du importere BooksModule inn i AppModule for å gjøre det funksjonelt. Du bør også bestå BooksModule til for RootAsync som vist nedenfor.

import { BooksModule } fra'./books/books.module';
/**
 * annen import
*/

@Modul({
importerer: [
ConfigModule.forRoot({
last: [mongodbConfig],
isGlobal: ekte
}),
NestGraphQLModule.forRootAsync({
sjåfør: ApolloDriver,
inject: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
autoSchemaFile: join (process.cwd(), 'src/schema.gql'),
installSubscriptionHandlers: ekte,
sortSchema: ekte,
lekeplass: ekte,
debug: configService.get<boolsk>("DEBUG"),
opplastinger: falsk,
}),
}),
MongooseModule.forRootAsync({
inject: [ConfigService],
useFactory: asynkron (configService: ConfigService) => ({
uri: configService.get('MONGO_URI')
})
}),
BooksModule,
],
kontrollere: [AppController],
leverandører: [AppService],
})

eksportklasse AppModule {}

Du kan teste koden ved å kjøre npm kjørestart: dev i terminalen din, og applikasjonen din skal starte på port 3000.

Åpen localhost: 3000/graphql i nettleseren din for å vise Graphiql grensesnitt hvor du kan teste spørringer og mutasjoner. Her er et eksempel som viser et søk:

Og her er et eksempel på en mutasjon:

Bygg effektive APIer med NestJS og GraphQL

Å bygge en GraphQL API i NestJS med MongoDB ved å bruke Mongoose innebærer å definere et skjema for GraphQL API, et skjema for Mongoose-modellen, en tjeneste for å samhandle med databasen, og en resolver for å kartlegge GraphQL-operasjoner til tjeneste metoder.

NestJS har innebygd funksjonalitet for å bygge API-er, inkludert dekoratører for å definere ruter, vakter for å beskytte dem, og mellomvare for håndtering av forespørsler og svar. Den støtter også andre databaser som PostgreSQL, MySQL og SQLite, så vel som andre GraphQL-biblioteker som Apollo og TypeGraphQL.