Zbuduj swój własny interfejs API, korzystając z tych popularnych technologii internetowych.

GraphQL i NestJS tworzą doskonałe partnerstwo, które zapewnia solidną podstawę dla interfejsów API i łatwą w użyciu platformę do tworzenia skalowalnych aplikacji internetowych. To połączenie jest idealne do tworzenia aplikacji gotowych do produkcji, a oba są bardzo istotnymi narzędziami w dzisiejszym ekosystemie technologicznym.

Dowiedz się więcej o tym, jak zbudować interfejs API przy użyciu obu produktów.

Co to jest GraphQL?

GraphQL to język zapytań i manipulacji danymi można użyć do tworzenia interfejsów API w bardziej precyzyjny i zwięzły sposób. GraphQL zapewnia pełny i adekwatny opis danych istniejących w API i daje klientowi możliwość uzyskania dokładnie potrzebnych danych.

GraphQL zapewnia wiele funkcji, których brakuje interfejsom API REST, od precyzyjnych zapytań o dane po lepsze narzędzia dla programistów, takie jak grafika redaktor. Umożliwia także wysyłanie zapytań o wiele zasobów za pomocą jednego żądania.

instagram viewer

Co to jest NestJS?

NestJS to progresywna platforma Node.js, której można używać do tworzenia skalowalnych i wydajnych aplikacji po stronie serwera. NestJS zapewnia wiele wtyczek wraz z narzędziami do szybkiego i łatwego programowania, w tym obsługę GraphQL, GRPC, WebSockets itp.

NestJS jest dobrze znany w ekosystemie ze zoptymalizowanej struktury projektu z wykorzystaniem modułów, kontrolerów, usług i schematów. Wbudowany interfejs CLI umożliwia tworzenie ustrukturyzowanej architektury API. Możesz użyć zasady wstrzykiwania zależności kontrolować, w jaki sposób części aplikacji komunikują się ze sobą.

Implementacja GraphQL z NestJS i MongoDB

Zanim zbudujesz API za pomocą NestJS i GraphQL, musisz mieć dostępne odpowiednie zależności. Potrzebujesz zainstalować Node.js i NestJS, które możesz zainstalować, uruchamiając npm i -g @nestjs/cli.

Poniższy przykład to prosta aplikacja, która przechowuje informacje o książkach. Uruchom następujące polecenie w swoim terminalu, aby utworzyć nową aplikację NestJS:

gniazdo nowe 

Przejdź do katalogu wygenerowanej aplikacji () i zainstaluj jego zależności za pomocą następującego polecenia:

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

Istnieją dwa główne podejścia do budowania interfejsów API GraphQL, a mianowicie:

  1. Podejście oparte na schemacie: gdzie opisujesz API w plikach definicji schematu lub SDL, a NestJS generuje na ich podstawie definicje TypeScript.
  2. Podejście oparte na kodzie: gdzie definiujesz zapytania, mutacje i inne funkcjonalności GraphQL za pomocą klas i dekoratorów TypeScript, a NestJS generuje na ich podstawie pliki SDL.

W poniższym przykładzie opisano, jak używać podejścia opartego na kodzie.

Najpierw musisz zainicjować GraphQL w swoim Moduł aplikacji I połącz go z bazą danych MongoDB:

// aplikacja.moduł.ts
import { Moduł } z'@nestjs/wspólny';
import { GraphQLModuł Jak Moduł NestGraphQLM} z'@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } z'@nestjs/apollo';
import { dołączyć } z'ścieżka';
import {Moduł Mongoose} z'@nestjs/mangusta';
import { Kontroler aplikacji } z„./kontroler aplikacji”;
import { Usługa aplikacji } z„./usługa.aplikacji”;
import { ConfigModule, ConfigService } z'@nestjs/config';
import mongodbConfig z„./config/mongodb.config”;

@Moduł({
import: [
ConfigModule.forRoot({
załaduj: [mongodbConfig],
jestGlobalny: PRAWDA
}),
NestGraphQLModule.forRootAsync({
kierowca: ApolloDriver,
wstrzyknąć: [ConfigService],
użyjFabryka: asynchroniczny (configService: ConfigService) => ({
autoSchemaFile: dołącz (process.cwd(), „źródło/schemat.gql”),
installSubscriptionHandlers: PRAWDA,
SortujSchemat: PRAWDA,
plac zabaw: PRAWDA,
debugowanie: configService.get<wartość logiczna>("ODPLUSKWIĆ"),
przesłane: FAŁSZ,
}),
}),
MongooseModule.forRootAsync({
wstrzyknąć: [ConfigService],
użyjFabryka: asynchroniczny (configService: ConfigService) => ({
uri: configService.get(„MONGO_URI”)
})
}),
],
kontrolery: [Kontroler aplikacji],
dostawcy: [AppService],
})

eksportklasa Moduł aplikacji {}

Ten moduł importuje pliki Moduł GraphQLM z @nestjs/graphql i MangustaModuł z @nestjs/mongoose który pomaga połączyć się z MongoDB. The plik autoschematu właściwość określa lokalizację wygenerowanego pliku schematu, a plik SortujSchemat właściwość gwarantuje, że pola są uporządkowane alfabetycznie.

Oto, co twój MongoDB konfiguracja plik powinien wyglądać tak:

import { zarejestruj jako } z'@nestjs/config';

/**
 * Konfiguracja połączenia z bazą danych Mongo
 */
eksportdomyślny zarejestruj jako ('mongodb', () => {
konst {
MONGO_URI
} = proces.env;

powrót {
adres: `${MONGO_URI}`,
};
});

Definiowanie schematu GraphQL

Po skonfigurowaniu połączeń GraphQL i MongoDB należy zdefiniować zapytania i mutacje GraphQL w celu wygenerowania schematu (schemat.gql) plik.

Pisanie zapytań

w podejście oparte na pierwszym kodzie, tworzysz model za pomocą Rodzaj obiektu dekorator. Później przekształcisz ten model w typ GraphQL.

Na przykład:

// book.model.ts
import { Pole, typ obiektu } z'@nestjs/graphql';
import { Rekwizyt, Schemat, Fabryka Schematów} z'@nestjs/mangusta';
import { Dokument } z'mangusta';

eksporttyp BookDocument = Książka i dokument;

@Rodzaj obiektu()
@Schemat()
eksportklasa Książka {
@Pole()
tytuł: strunowy;

@Pole()
autor: strunowy;

@Pole()
Data publikacji: wartość logiczna;
}

eksportkonst BookSchema = SchemaFactory.createForClass (książka);

GraphQL domyślnie nie może korzystać z utworzonych schematów. Aby działały, potrzebujesz usługi resolvera, która zawiera funkcje do wykonywania typów GraphQL. Możesz to zrobić za pomocą Rozwiązujący dekorator.

// książki.resolver.ts
import { Resolwer, zapytanie, mutacja, argumenty, identyfikator } z'@nestjs/graphql';
import { Książka } z„./książka.model”;
import { BookService } z„./książki.usługa”;

@Resolver(() => Książka)
eksportklasa BookResolver {
konstruktor(prywatny Tylko do odczytu Usługa książki: Usługa książki) { }

@Zapytanie(() => [Książka])
asynchroniczny książki(): Obietnica {
powrótTen.bookService.findAll();
}

@Zapytanie(() => Książka)
asynchroniczny książka(@Args('ID', { typ: () => Zrobiłem: strunowy): Obietnica {
powrótTen.bookService.findOne (identyfikator);
}
}

Możesz wdrożyć tzw BookService,przywożone powyżej, jak następuje:

// książki.serwis.ts
import { Do wstrzykiwań } z'@nestjs/wspólny';
import {Model wstrzykiwania} z'@nestjs/mangusta';
import { Model } z'mangusta';
import { Książka, Dokument Księgi } z„./książka.model”;

@Do wstrzykiwań()
eksportklasa BookService {
konstruktor(@InjectModel(nazwa.książki) prywatny książkaModel: Model) { }

asynchroniczny Znajdź wszystko(): Obietnica {
powrótTen.bookModel.find().exec();
}

asynchroniczny znajdźJeden (identyfikator: strunowy): Obietnica {
powrótTen.bookModel.findById (id).exec();
}
}

Musisz także dodać BookResolver do listy dostawców w książki.moduły.ts.

import { Moduł } z"@nestjs/wspólny";
import {Moduł Mongoose} z"@nestjs/mangusta";
import { BookService } z„./książki.usługa”;
import { BookResolver } z„./books.resolver”;
import { Książka, schemat książki } z„./książka.model”;

@Moduł({
dostawcy: [
Serwis Rezerwacyjny,
BookResolver
],
importuje: [MongooseModule.forFeature([
{
nazwa: Imię.książki,
schemat: BookSchema,
},
]),
],
})

eksportklasa KsiążkiModuł {}

Praca z mutacjami

Podczas gdy używasz zapytania do pobierania danych w GraphQL, mutacje tworzą lub aktualizują dane w bazie danych. Aby tworzyć mutacje, musisz zaakceptować dane od użytkowników. The Typ wejścia przydaje się tutaj dekorator, który zamienia klasę na typ wejściowy GraphQL.

// book.input.ts
import { Typ wejścia, pole } z'@nestjs/graphql';

@InputType()
eksportklasa Zarezerwuj Wejście {
@Pole()
tytuł: strunowy;

@Pole()
autor: strunowy;

@Pole()
Data publikacji: wartość logiczna
}

Możesz teraz zaktualizować książki.resolver.ts wyglądać tak:

import { Resolwer, zapytanie, mutacja, argumenty, identyfikator } z'@nestjs/graphql';
import { Książka } z„./książka.model”;
import { BookService } z„./książki.usługa”;
import { Wprowadzanie książki } z'./book.input';

@Resolver(() => Książka)
eksportklasa BookResolver {
konstruktor(prywatny Tylko do odczytu Usługa książki: Usługa książki) { }

@Mutacja(() => Książka)
asynchroniczny stwórzKsiążkę(@Args('wejście') wejście: BookInput): Obietnica {
powrótTen.bookService.create (wejście);
}

@Mutacja(() => Książka)
asynchroniczny aktualizacjaksiążki (
@Args('ID', { typ: () => Zrobiłem: strunowy,
@Args('wejście') wejście: BookInput,
): Obietnica {
powrótTen.bookService.update (identyfikator, dane wejściowe);
}

@Mutacja(() => Książka)
asynchroniczny usuńKsiążkę(@Args('ID', { typ: () => Zrobiłem: strunowy): Obietnica {
powrótTen.bookService.delete (identyfikator);
}
}

I książki.serwis.ts lubię to:

import { Do wstrzykiwań } z'@nestjs/wspólny';
import {Model wstrzykiwania} z'@nestjs/mangusta';
import { Model } z'mangusta';
import { Książka, Dokument Księgi } z„./książka.model”;

@Do wstrzykiwań()
eksportklasa BookService {
konstruktor(@InjectModel(nazwa.książki) prywatny książkaModel: Model) { }

asynchroniczny tworzyć (księga: książka): Obietnica {
konst nowaKsiążka = nowyTen.bookModel (książka);
powrót nowaKsiążka.save();
}

asynchroniczny aktualizacja (identyfikator: strunowy, książka Książka): Obietnica {
powrótTen.bookModel.findByIdAndUpdate (identyfikator, książka, { nowy: PRAWDA }).exec();
}

asynchronicznyusuwać(ID: strunowy): Obietnica {
powrótTen.bookModel.findByIdAndDelete (id).exec();
}
}

The @Mutacja dekorator oznacza funkcję jako typ mutacji, a @Args dekorator pobiera wszystkie dane wejściowe przekazane do funkcji.

Na koniec należy zaimportować plik Moduł książek do Moduł aplikacji aby był funkcjonalny. Powinieneś także przejść tzw Moduł książek Do forRootAsync jak widać poniżej.

import { Moduł książek } z„./książki/książki.moduł”;
/**
 * inny import
*/

@Moduł({
import: [
ConfigModule.forRoot({
załaduj: [mongodbConfig],
jestGlobalny: PRAWDA
}),
NestGraphQLModule.forRootAsync({
kierowca: ApolloDriver,
wstrzyknąć: [ConfigService],
użyjFabryka: asynchroniczny (configService: ConfigService) => ({
autoSchemaFile: dołącz (process.cwd(), „źródło/schemat.gql”),
installSubscriptionHandlers: PRAWDA,
SortujSchemat: PRAWDA,
plac zabaw: PRAWDA,
debugowanie: configService.get<wartość logiczna>("ODPLUSKWIĆ"),
przesłane: FAŁSZ,
}),
}),
MongooseModule.forRootAsync({
wstrzyknąć: [ConfigService],
użyjFabryka: asynchroniczny (configService: ConfigService) => ({
uri: configService.get(„MONGO_URI”)
})
}),
KsiążkiModuł,
],
kontrolery: [Kontroler aplikacji],
dostawcy: [AppService],
})

eksportklasa Moduł aplikacji {}

Możesz przetestować kod, uruchamiając npm uruchom start: dev w terminalu, a aplikacja powinna pomyślnie uruchomić się na porcie 3000.

otwarty lokalny host: 3000/grafql w przeglądarce, aby wyświetlić grafika interfejs, w którym możesz testować zapytania i mutacje. Oto przykład, który pokazuje zapytanie:

A oto przykład mutacji:

Twórz wydajne interfejsy API za pomocą NestJS i GraphQL

Budowanie API GraphQL w NestJS z MongoDB przy użyciu Mongoose obejmuje zdefiniowanie schematu dla GraphQL API, schematu dla modelu Mongoose, usługa do interakcji z bazą danych oraz resolver do mapowania operacji GraphQL na usługę metody.

NestJS ma wbudowaną funkcjonalność do tworzenia interfejsów API, w tym dekoratory do definiowania tras, strażników do ich ochrony oraz oprogramowanie pośredniczące do obsługi żądań i odpowiedzi. Obsługuje również inne bazy danych, takie jak PostgreSQL, MySQL i SQLite, a także inne biblioteki GraphQL, takie jak Apollo i TypeGraphQL.