Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Leitfaden zu Nest.js – Erstellen einer REST-API mit Nest und Node

Als Node.js-Backend-Entwickler stimmen Sie zu, dass Node.js standardmäßig sehr schlicht ist und keine Annahmen darüber macht, was Sie beim Erstellen einer App benötigen. Daher sind Sie dafür verantwortlich, alles einzurichten, was Sie in einer App verwenden möchten, einschließlich der Handhabung des Routings, der Durchführung von API-Aufrufen, der Einrichtung von TypeScript oder Web Sockets und sogar grundlegender Dinge wie Codeorganisation, Dateistruktur und Namenskonventionen .

Die Verwaltung einer umfangreichen Anwendung kann eine schwierige Aufgabe sein, insbesondere wenn sie nicht mit einer klaren Struktur und strengen Richtlinien für die Code-Organisation entworfen wurde.

Nest.js versucht, einige dieser Probleme zu lösen, indem es eine Abstraktion um Node.js erstellt, sodass Sie sich als Entwickler auf das Anwendungsproblem und nicht auf andere winzige Implementierungsdetails konzentrieren können.

In diesem Leitfaden lernen Sie die Kerngrundlagen von Nest.js von Grund auf kennen. Ziel ist es, Sie auf den neuesten Stand zu bringen, damit Sie mit Hilfe von Nest.js im Handumdrehen Node.js-Anwendungen der Enterprise-Klasse erstellen können.

Alles, was wir in diesem Leitfaden lernen werden, wird schrittweise erfolgen; deckt viele Themen zu Einführungskonzepten ab. Um das Beste aus diesem Leitfaden herauszuholen, ist es hilfreich, mitzuprogrammieren.

Lasst uns gleich eintauchen, Leute!

Quellcode: Wie üblich können Sie den auf gehosteten Quellcode forken und basteln GitHub.

Hinweis: Wir werden Postman verwenden, um die API in unserer Demo zu testen. Sie können es auf der herunterladen Postbote-Download-Seite. Alternativ können Sie auch einfach den Browser, die Kommandozeile, verwenden curl Tool oder ein anderes Tool, mit dem Sie möglicherweise vertraut sind.

Was ist Nest.js?

Stellen Sie sich Nest.js als eine Obermenge von Node.js vor, die schwierige Aufgaben, Tools und Boilerplate-Code abstrahiert und gleichzeitig ein vollwertiges Toolkit für Ihre Anwendungsentwicklung mit modernem JavaScript und TypeScript hinzufügt.

Nest.js bietet eine sofort einsatzbereite Anwendungsarchitektur, die es Entwicklern und Teams ermöglicht, hoch skalierbare, testbare, lose gekoppelte und leicht zu wartende Anwendungen zu erstellen, indem sie leicht verfügbare und prominente Optionen und Module in der Community nutzen, wie sie beispielsweise in verfügbar sind Express.js-Anwendungen. Sie könnten sogar Express (das standardmäßig unter der Haube verwendet wird) gegen Fastify austauschen. Dies würde jedoch bedeuten, dass Sie möglicherweise andere Fastify-kompatible Bibliotheken in Ihrer Anwendung verwenden müssen.

Es kombiniert die Funktionen der funktionalen Programmierung, der objektorientierten Programmierung und der funktionalen reaktiven Programmierung und verfügt über mehr als 52.4 Sterne und 6.2 Gabeln GitHub und einer wöchentlichen Downloadzahl von bis zu 1,784,004 ist das progressive Node.js-Framework eine beliebte Wahl für die Erstellung effizienter, skalierbarer und unternehmenstauglicher serverseitiger Anwendungen.

Funktionen von Nest.js

Die folgenden Gründe führen dazu, dass sich Nest.js zu einem so beliebten Node.js-Framework entwickelt hat:

  1. Nest.js wurde entwickelt, um Entwicklern dabei zu helfen, sowohl monolithische Anwendungen als auch Microservices zu erstellen.
  2. Obwohl es leistungsstark ist, lässt es sich auch entwicklerfreundlich damit arbeiten. einfach zu bedienen, schnell zu erlernen und einfach anzuwenden.
  3. Es nutzt sofort TypeScript (eine Obermenge von JavaScript) und bietet Entwicklern die Möglichkeit, wartbaren Code ohne Laufzeitfehler zu schreiben.
  4. Es verfügt über eine Befehlszeilenschnittstelle, die dazu beiträgt, die Produktivität der Entwickler zu steigern und die Entwicklung zu vereinfachen.
  5. Beim Erstellen mit Nest.js werden Entwicklungsprozesse verbessert und Zeit gespart, unabhängig davon, ob Sie ein Minimum Viable Product erstellen oder an einer Anwendung arbeiten, da Nest standardmäßig über eine erstaunliche Projektordnerstruktur verfügt.
  6. Es unterstützt eine Vielzahl von Nest-spezifischen Modulen, die bei der Integration gängiger Konzepte und Technologien helfen, darunter TypeORM, GraphQL, Protokollierung, Validierung, Mongoose, WebSockets, Caching usw.
  7. Nest.js kann sich rühmen, über die beste Dokumentation für jedes verfügbare Framework zu verfügen. Die Dokumentation ist ausführlich, leicht verständlich und trägt dazu bei, Zeit beim Debuggen zu sparen, da sie mühelos zur Verfügung steht, wenn eine Lösung für ein Problem benötigt wird.
  8. Nest.js lässt sich in Jest integrieren, was das Schreiben von Komponententests für Ihre Anwendungen vereinfacht.
  9. Es ist sowohl für kleine als auch große Unternehmensanwendungen konzipiert.

Erstellen eines Nest.js-Projekts

Um mit Nest.js auf Ihrem lokalen Computer zu beginnen, müssen Sie zunächst die Nest Command Line Interface (CLI) installieren, die dabei hilft, einen neuen Nest.js-Projektordner zu erstellen und den Ordner mit Kerndateien und Modulen zu füllen, die für a benötigt werden Nest.js-Anwendung.

Führen Sie den folgenden Befehl aus, um die Nest.js-Befehlszeilenschnittstelle zu installieren:

$ npm i -g @nestjs/cli
// Or
$ yarn global add @nestjs/cli
// Or
$ pnpm add -g @nestjs/cli

Sobald Sie die Nest.js-CLI erfolgreich global auf Ihrem lokalen Computer installiert haben, können Sie sie ausführen nest in der Befehlszeile, um verschiedene Befehle anzuzeigen, auf die wir zugreifen können:

$ nest

Ergebnisse in:

Usage: nest  [options]

Options:
  -v, --version                                   Output the current version.
  -h, --help                                      Output usage information.

Commands:
  new|n [options] [name]                          Generate Nest application.
  build [options] [app]                           Build Nest application.
  start [options] [app]                           Run Nest application.
  info|i                                          Display Nest project details.
  add [options]                          Adds support for an external library to your project.
  generate|g [options]  [name] [path]  Generate a Nest element.
    Schematics available on @nestjs/schematics collection:
      ┌───────────────┬─────────────┬──────────────────────────────────────────────┐
      │ name          │ alias       │ description                                  │
      │ application   │ application │ Generate a new application workspace         │
      │ class         │ cl          │ Generate a new class                         │
      │ configuration │ config      │ Generate a CLI configuration file            │
      │ controller    │ co          │ Generate a controller declaration            │
      │ decorator     │ d           │ Generate a custom decorator                  │
      │ filter        │ f           │ Generate a filter declaration                │
      │ gateway       │ ga          │ Generate a gateway declaration               │
      │ guard         │ gu          │ Generate a guard declaration                 │
      │ interceptor   │ itc         │ Generate an interceptor declaration          │
      │ interface     │ itf         │ Generate an interface                        │
      │ middleware    │ mi          │ Generate a middleware declaration            │
      │ module        │ mo          │ Generate a module declaration                │
      │ pipe          │ pi          │ Generate a pipe declaration                  │
      │ provider      │ pr          │ Generate a provider declaration              │
      │ resolver      │ r           │ Generate a GraphQL resolver declaration      │
      │ service       │ s           │ Generate a service declaration               │
      │ library       │ lib         │ Generate a new library within a monorepo     │
      │ sub-app       │ app         │ Generate a new application within a monorepo │
      │ resource      │ res         │ Generate a new CRUD resource                 │
      └───────────────┴─────────────┴──────────────────────────────────────────────┘

Hier wird Ihnen gezeigt, wie Sie die Befehle verwenden, und Sie können nun darauf tippen new|n [options] [name] Befehl zum Erstellen Ihres allerersten Nest.js-Projekts:

$ nest new getting-started-with-nestjs
// Or
$ nest n getting-started-with-nestjs

Als nächstes werden Sie gefragt, welchen Paketmanager Sie verwenden möchten:

? Which package manager would you ❤️ to use? (Use arrow keys)
  npm
  yarn
> pnpm

Fühlen Sie sich frei, den Paketmanager Ihrer Wahl zu wählen, ich werde mitmachen pnpm. Dies liegt daran, dass es etwa dreimal effizienter und schneller als NPM ist und mit einem schnellen Cache-System auch schneller als Yarn ist.

Nach der Auswahl eines Paketmanagers wird der Installationsprozess fortgesetzt, dann wird die Nest.js-App erstellt.

Jetzt kannst du cd in das neu erstellte Projekt ein und öffnen Sie es mit einem Editor Ihrer Wahl:

$ cd getting-started-with-nestjs

Nachdem das Projekt nun erstellt wurde, können wir es mit einem der folgenden Befehle ausführen:

$ npm run start
// Or
$ yarn start
// Or
$ pnpm run start

Wenn Sie sich das ansehen package.json In der Datei sehen Sie im Skriptsegment den Wert für pnpm run start is nest start:


    
"start": "nest start",

Das bedeutet, dass Sie die Nest.js-App auch ausführen können, indem Sie Folgendes ausführen:

$ nest start

Ein Blick auf die Nest.js-Projektstruktur

Schauen wir uns einmal genauer an, wie eine Nest-App aufgebaut ist:

/package.json

Das package.json Die Datei ist das Herzstück des Node.js- und damit auch des Nest.js-Projekts. Es enthält alle Metadaten zum Projekt und definiert verschiedene funktionale Eigenschaften des Projekts, die zum Installieren von Anwendungsabhängigkeiten oder zum Ausführen von Projektskripten erforderlich sind.

Wir haben bereits die Fähigkeit des gesehen start Skripte.

Das start:dev Das Profil ermöglicht es, auf Änderungen in der Anwendung zu achten und diese automatisch neu zu laden, ohne dass die Anwendung angehalten und neu gestartet werden muss – und es ist für die Entwicklung gedacht. Der start:prod Das Skript ist nützlich, wenn Sie testen möchten, ob Ihre Anwendung produktionsbereit ist, und wenn Sie sie zusammen mit anderen Skripten zum Testen der Nest.js-App in der Produktion bereitstellen.

@nestjs/platform-express definiert Express als Standard-HTTP-Server in einer Nest-Anwendung.

/tsconfig.json

Das tsconfig.json Datei ist eine in JSON (JavaScript Object Notation) geschriebene Datei, die TypeScript-bezogene Optionen definiert, die zum Kompilieren der Nest-App erforderlich sind.

/nest-cli.json

Darin sind Metadaten enthalten, die zum Erstellen, Organisieren oder Bereitstellen von Nest-Anwendungen erforderlich sind.

/test

Dieses Verzeichnis enthält alle Dateien, die zum Ausführen von Nest-Tests erforderlich sind. Nest verwendet das Jest-Framework zum Testen mit der Jest-Konfiguration im jest-e2e.json Datei.

/src

Das src Das Verzeichnis ist der übergeordnete Ordner für den Kern des Nest-Projekts. Es hält die main.ts Datei, die die Datei ist, in der die Nest-App gestartet wird. Die Aufgabe des main.ts Datei geladen werden soll AppModule das aus importiert wird /src/app.module.ts.

Später in diesem Handbuch erfahren Sie mehr über Module. eine der Hauptkomponenten einer Nest.js-Anwendung.

Das AppModule ist eine Klasse, die als Modul unter Verwendung von erstellt wird @Module Dekorateur. Im app.module.ts Datei, AppService für ./app.service und AppController für ./app.controller werden ebenfalls importiert.

Das AppController ist auch eine Klasse, die mit erstellt wird @Controller Dekorateur, während die AppService ist eine Klasse, die mit erstellt wird @Injectable Anmerkung.

Das Coole an Nest ist, dass es nur sehr wenige Dekoratoren enthält, die einer Klasse Metadaten hinzufügen, und dass Metadaten den Zweck dieser Klasse definieren, sodass:

  • @Controller()wandelt eine Klasse in einen Controller um.
  • @Module() wandelt eine Klasse in ein Modul um.
  • @Injectable() wandelt eine Klasse in einen Anbieter um.

Auch in der src Verzeichnis ist das app.controller.spec.ts Datei, die eine Testdatei für Controller ist.

Wir können die App mit ausführen nest start.

Die App wird gestartet um http://localhost:3000 in Ihrem Browser:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Wir können den angezeigten Inhalt ändern http://localhost:3000, indem Sie zum gehen app.service.ts Datei, in der der Anbieter für die Indexroute definiert wurde.

Die Bausteine ​​einer Nest.js-App

Eine Nest.js-Anwendung besteht aus drei Hauptkomponenten:

  1. Module
  2. Regler
  3. Anbieter

Um mehr über die Bausteine ​​einer Nest-App zu erfahren, bereinigen wir zunächst das Nest-Projekt, indem wir die löschen app.controller.spec.ts, ./app.service, app.module.ts und ./app.controller Dateien; einfach gehen main.ts, um einen Entwicklungslebenszyklus von Grund auf zu emulieren.

An diesem Punkt entfernen wir das Importierte AppModule Datei von main.ts, wir werden aufgefordert, dass ein Argument für „Modul“ nicht angegeben wurde.

Um die Bausteine ​​einer Nest-App zu demonstrieren, werfen wir einen Blick auf eine einfache Benutzerprofilimplementierung, indem wir eine REST-API erstellen, um CRUD-Vorgänge für ein Objekt abzuwickeln.

Module

Im src Ordner einen neuen erstellen app.module.ts Datei, dann erstellen Sie eine AppModule Klasse, die wir exportieren.

Als nächstes importieren Sie die AppModule Klasse hinein main.ts, und Renn nest start.

Navigieren http://localhost:3000 in Ihrem Browser und Sie erhalten einen 404-Fehler:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Dies liegt daran, dass wir noch keine Route für die Basis-URL der Nest-App definiert haben.

, Die Skeptiker erwähnt, wie Carrie Poppy ein Medikament namens ColdCalm, um sie mit ihrer Krankheit%2phelfen gekauft. Turns out ColdCalm war keine tatsächliche Wirksamkeit homöopathischer und musste es. Carrie Called ... app.module.ts, Wir haben das AppModule Die Klasse, die wir haben, ist noch kein Nest-Modul. Um es zu einem Nest-Modul zu machen, fügen wir das hinzu @Module() Dekorateur, der aus importiert wird @nestjs/commondann übergeben wir ein leeres Objekt.



import { Module } from '@nestjs/common';
@Module({})

export class AppModule {}

Jetzt haben wir ein Nest.js-Modul!

Hinweis: Ein Modul ist eine Klasse, die mit a annotiert ist @Module() Dekorateur.

Jede Nest-Anwendung verfügt über ein Stammmodul, das als Einstiegspunkt für die Auflösung der Struktur und Beziehungen einer Nest-Anwendung dient.

Es wird dringend empfohlen, mehrere Module zu verwenden, um die Komponenten Ihrer Anwendung zu organisieren.

Das @Module() Mit dem Decorator können Entwickler Metadaten zu einer Klasse in der Nest-App definieren.

Wenn es mehrere Module gibt, wie z. B. ein Benutzermodul, ein Bestellmodul, ein Chatmodul usw., ist das app.module.ts sollte zur Registrierung aller anderen Module der Nest-App verwendet werden.

Routen erstellen; Controller

Zum Erstellen von Routen in Nest-Anwendungen werden Controller benötigt. Der Zweck eines Controllers besteht darin, spezifische Anfragen für eine Nest-Anwendung zu erhalten. Steuern des Anforderungs- und Antwortzyklus für verschiedene Routen innerhalb der Anwendung.

Wenn eine HTTP-Anfrage vom Client an die Nest-Anwendung gestellt wird, verarbeitet die Route, die mit der Route übereinstimmt, über die die Anfrage gestellt wird, die Anfrage und gibt die entsprechende Antwort zurück.

Um einen Controller in einer Nest-App zu erstellen, müssen wir den verwenden @Controller() Dekorateur.

Im src Verzeichnis, erstellen Sie eine neue Datei app.contoller.ts, und darin können wir einen Nest-Controller definieren:

import { Controller } from '@nestjs/common';

@Controller({})

export class AppController {}

Das ist es! Wir haben einen sehr schönen Controller, aber um eine neue Route zu erstellen, müssen wir zuerst unsere Nest-App über den erstellten Controller informieren.

Um dies zu erreichen, achten wir auf den Import AppController in app.module.ts und definieren Sie Informationen zu den Controllern in @Module() decorator – als Array von Controllern:



import { Module } from '@nestjs/common';
import { AppController } from './app.controller';

@Module({
  controllers: [AppController],
})

export class AppModule {}

Bearbeitung von GET-Anfragen

Dann definieren wir ein einfaches getUser() Route (mit der @Get() Der Dekorator, der für die Verarbeitung von HTTP-GET-Anfragen an einen angegebenen Pfad verwendet wird, dient als Basisroute. Wir können im Browser unter darauf zugreifen https://localhost:3000:



import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return 'I am a great person';
  }
}

Das führt zu:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Hmm, hier geben wir nur einen String zurück, aber was wäre, wenn wir ein Objekt zurückgeben wollten? Anstelle einer Zeichenfolge können wir ein Objekt definieren:



import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
}

Navigieren http://localhost:3000 in Ihrem Browser und Sie sehen das Objekt:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Wie wäre es, wenn Sie abseits der Basisroute eine ähnliche Route erstellen würden? http://localhost:3000/user zum Abrufen aller Benutzer?

Wir können einen Controller erstellen, der eine solche Route auf verschiedene Arten verwaltet.

Eine Möglichkeit wäre, eine neue Methode zu definieren, indem man die verwendet @Get() Dekorateur/Handler.

import { Controller, Get } from '@nestjs/common';

@Controller({})

export class AppController {
  @Get()
  getUser() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
}

Nest.js stellt Dekoratoren oder Handler für alle verschiedenen HTTP-Methoden bereit, einschließlich @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options() und @Head().

Das @All() decorator definiert einen Endpunkt, der alle verschiedenen Methoden verarbeitet.

Bearbeitung von POST-Anfragen

Wir können auch POST-Anfragen zum Speichern von Daten in der Datenbank definieren, indem wir die verwenden @Post() Dekorateur:

import { Controller, Post } from '@nestjs/common';

@Controller({})
export class AppController {
  @Post()
  store() {
    return 'Post request successful';
  }
}

Anschließend testen wir die POST-Anfrage mit Postman und stellen fest, dass die Zeichenfolge wie definiert erfolgreich zurückgegeben wurde.

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Sie fragen sich vielleicht: Was ist, wenn ich auch mehr als nur Daten zurückgeben möchte? Vielleicht, um Daten zu senden.

Dazu müssen Sie die Daten wie gezeigt in die Route-Methode einfügen:

import { Controller, Post, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller({})
export class AppController {
  @Post()
  store(@Req() req: Request) {
    return req.body;
  }
}

Wenn wir nun die POST-Anfrage mit Postman testen, können wir die gesendeten Daten anzeigen. In diesem Fall handelt es sich lediglich um ein leeres Objekt:

Sehen Sie sich unseren praxisnahen, praktischen Leitfaden zum Erlernen von Git an, mit Best Practices, branchenweit akzeptierten Standards und einem mitgelieferten Spickzettel. Hören Sie auf, Git-Befehle zu googeln und tatsächlich in Verbindung, um es!

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Dynamisches Routing mit Routenparametern

Angenommen, Sie möchten dynamische Daten als Teil einer Anfrage akzeptieren. Zuerst müssen wir das Token im Pfad der Route definieren, um die dynamische Position auf der Route/URL zu notieren, und dann das verwenden @Param() Decorator kann auf den Routenparameter wie folgt zugegriffen werden:

import { Controller, Get, Param } from '@nestjs/common';

@Controller({})
export class AppController {
  @Get('/:userId')
  getUser(@Param() userId: number) {
    return userId;
  }
}

Das userId wird erfolgreich zurückgegeben:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Umgang mit asynchronen Anfragen

Nest.js kann asynchrone Anfragen, die ein Versprechen zurückgeben, mit verschiedenen Ansätzen verarbeiten:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  async findAll(): Promise {
    return [];
  }
}

Im obigen Ansatz wird Asynchronität mithilfe von gehandhabt async Stichwort. Ein anderer Ansatz besteht darin, beobachtbare RxJS-Streams zurückzugeben:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  findAll(): Observable {
    return of([]);
  }
}

Hier abonniert Nest.js die Quelle unter der Haube und übernimmt nach Abschluss des Streams automatisch den zuletzt ausgegebenen Wert.

Umgang mit Weiterleitungen in Nest

Das @Redirect() Decorator wird verwendet, um eine Antwort an eine andere URL umzuleiten. Der @Redirect() decorator akzeptiert zwei Argumente – die URL, zu der umgeleitet werden soll, und den Statuscode bei der Umleitung, die beide optional sind:

import { Controller, Get} from '@nestjs/common';

@Controller({})
export class AppController {
  @Get()
  @Redirect('https://www.ucheazubuko.com', 302)
  getSite() {
    return { url: 'https://stackabuse.com' };
  }
}

Statuscode wird zurückgegeben

Um den Statuscode für jede auf dem Nest.js-Server verarbeitete Anfrage zurückzugeben, muss der @HttpCode(…) kommt problemlos durch.

In Nest ist der Standardstatuscode für GET-Anfragen 200, eine POST-Anfrage 201 und eine Fehleranfrage 304

Der Statuscode für eine Serveranfrage kann wie folgt definiert werden:

import { Controller, Post, HttpCode } from '@nestjs/common';

@Controller({})
export class AppController {
  @Post()
  @HttpCode(204)
  create() {
    return 'This action adds a new user to the app.';
  }
}

Bearbeitung von DELETE-Anfragen

Ähnlich wie bei einer POST-Anfrage kann eine Löschanforderung folgendermaßen gehandhabt werden:

import { Controller, Delete, Param } from '@nestjs/common';

@Controller({})
export class AppController {
  @Delete('/:userId')
  delete(@Param() params: { userId: number }) {
    return params;
  }
}

Bearbeitung von UPDATE-Anfragen

Eine Anfrage zum Aktualisieren bestimmter Daten auf dem Server kann mit verarbeitet werden @Patch() Dekorateur:

import { Controller, Patch, Req} from '@nestjs/common';
import { Request } from 'express';

@Controller({})
export class AppController {
  @Patch('/:userId')
  update(@Req() req: Request) {
    return req.body;
  }
}

Nachdem wir nun verschiedene Möglichkeiten kennengelernt haben, typische Controller zu definieren, die wir oft auf einem robusten Server haben, ist es wichtig zu beachten, dass der Controller schlank, sauber und pro Anwendungsfall definiert sein sollte, sodass er auch dann verwendet werden kann, wenn es einen anderen Controller zum Definieren gibt user Routen, dann sollte ein separates Verzeichnis erstellt und für die Bearbeitung derselben reserviert werden – außerhalb der AppController.

Dann in user.controller.tskönnen wir alle darin enthaltenen Routenhandler so konfigurieren, dass ihnen ein Präfix vorangestellt wird /user/ indem Sie Code wie unten gezeigt schreiben:



import { Controller, Get } from '@nestjs/common';

@Controller('/user')
export class UserController {
  @Get()
  getUser() {
    return 'I am from the user controller';
  }
}

Als nächstes registrieren Sie sich UserController in den Arrays der Controller in app.modules.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserController } from './controllers/user/user.controller';

@Module({
  controllers: [AppController, UserController],
})

export class AppModule {}

Wenn wir zu navigieren https:localhost:3000/user, es wird erfolgreich zurückgegeben:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Um den Projektordner noch übersichtlicher zu halten, als er jetzt ist, können wir eine definieren user.module.ts Datei, in der wir die definieren werden UserController:

import { Module } from '@nestjs/common';
import { UserController } from './user.controller';

@Module({
  controllers: [UserController],
})

export class UserModule {}

Dann importieren UserModule in app.module.ts:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { UserModule } from './user/user.module';

@Module({
  controllers: [AppController],
  imports: [UserModule],
})

export class AppModule {}

Damit können wir den gleichen Effekt wie zuvor erzielen.

Hinweis: Nest macht es einfach, (Module) und (Co)Controller mit dem zu (g)enerieren nest g mo und nest g co Befehle. Spezifische Module, wie z user Module und Controller können auch schnell mit der Nest CLI erstellt werden, indem Sie die folgenden Befehle ausführen: nest g mo user – um ein Benutzermodul zu erstellen und nest g co user – um einen Benutzercontroller zu erstellen.

Anbieter

Der gesamte Abruf von Daten aus einer Datenbank sollte von Anbietern und nicht von Controllern durchgeführt werden, um eine Abstraktionsebene zwischen dem benutzerseitigen Code und dem Code zu schaffen, der mit potenziell sensiblen Daten interagiert. Zwischen diesen Ebenen kann eine Validierung eingerichtet werden, um eine ordnungsgemäße Datenbankverwaltung sicherzustellen. Mit der Nest CLI können wir Anbieter erstellen, indem wir Dienste generieren:

$ nest g s user

Dies schafft ein UserService wobei wir die gesamte Geschäftslogik für die definieren würden UserController, So dass UserController bearbeitet nur Anfragen und Antworten. In user.service.ts, wir sehen, dass die @Injectable() Der Dekorator wird zum Definieren der Klasse verwendet. In Nest ist die Verwendung von @Injectable() Der Dekorator dient dazu, Dienste, Repositorys oder Hilfsklassen in einen Anbieter umzuwandeln.

Anbieter werden über ihren Konstruktor in eine Klasse eingefügt. Schauen wir uns ein Beispiel genauer an.

Früher in user.controller.ts, hatten wir die Geschäftslogik zum Abrufen des Benutzerobjekts definiert, aber jetzt sollten wir dieselbe im definieren UserService:



import { Controller, Injectable } from '@nestjs/common';

@Controller({})

export class AppController {
  @Injectable()
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria'; };
  }
}

Als nächstes in der user.controller.ts Definieren wir einen Konstruktor in der Datei UserController Klasse. In diesem Konstruktor stellen wir ein privates bereit userService, was eine Art von ist UserService Klasse. Mit diesem privaten Zugriff können wir auf die Geschäftslogik zugreifen, die wir zuvor zum Abrufen der Benutzer definiert hatten:



import { Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';

@Controller('/user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUser() {
    return this.userService.get();
  }
}

Somit wird die UserController Klasse, hängt jetzt von der ab UserService Klasse in einem Konzept namens
Abhängigkeitsspritze.

Ebenso ist die Logik in beiden user.controller.ts und user.service.ts Dateien werden entsprechend aktualisiert:



import {
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUsers() {
    return this.userService.get();
  }
  @Get('/:userId')
  getUser(@Param() param: { userId: number }) {
    return this.userService.getUser(param);
  }
  @Post()
  store(@Req() req: Request) {
    return this.userService.create(req);
  }
  @Patch('/:userId')
  update(@Req() req: Request, @Param() param: { userId: number }) {
    return this.userService.update(req, param);
  }
  @Delete()
  delete(@Param() param: { userId: number }) {
    return this.userService.delete(param);
  }
}


import { Injectable } from '@nestjs/common';
import { Request } from 'express';

@Injectable()
export class UserService {
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
  getUser(param: { userId: number }) {
    return param;
  }
  create(req: Request) {
    return req.body;
  }
  update(req: Request, param: { userId: number }) {
    return { body: req.body, param };
  }
  delete(param: { userId: number }) {
    return param;
  }
}

Lassen Sie uns nun mithilfe von Postman überprüfen, ob die Endpunkte ordnungsgemäß funktionieren.

Entmystifizierung der Abhängigkeitsinjektion in Nest.js

Wenn Sie kleinere Komponenten einer Anwendung erstellen, beispielsweise eine Klasse oder ein Modul, ist Ihre Klasse möglicherweise auf die Funktionalität einer anderen Klasse oder eines anderen Moduls angewiesen, z. B. auf die Notwendigkeit, auf einen von einer anderen Klasse bereitgestellten HTTP-Dienst zuzugreifen, um API-Aufrufe durchzuführen, oder Serviceschichten, die mit der Persistenzschicht interagieren.

Abhängigkeiten können innerhalb von Controllern bereitgestellt werden Abhängigkeitsspritze.

Abhängigkeitsinjektion ist ein Programmierkonzept und -muster, das ausdrückt, wie Teile einer Anwendung an andere Teile der Anwendung übermittelt werden, die sie benötigen, und zwar so, dass eine hohe Kohäsion, aber eine lockere Kopplung gewährleistet ist.

Nest unterstützt die Abhängigkeitsinjektion und Sie können es in Ihren Nest-Anwendungen verwenden, um die Modularität Ihres Projekts zu verbessern.

Eine praktische Veranschaulichung sieht folgendermaßen aus:

Angenommen, Klasse A nutzt einige Funktionen von Klasse B. Dann heißt es, dass Klasse A von Klasse B abhängt. Um also Klasse B in Klasse A verwenden zu können, müssen wir zuerst eine Instanz von Klasse B erstellen (d. h. eine erstellen). Objekt der Klasse B): const b = new B ().
Die Übertragung der Aufgabe, eine Instanz einer Klasse auf eine andere Klasse zu erstellen und die Abhängigkeit in der bereitgestellten Klasse (die Injektorkomponente) direkt zu nutzen, wird als Abhängigkeitsinjektion bezeichnet.

Hinweis: Dependency Injection oder DI ist eines der grundlegenden Konzepte in Frameworks wie Spring Boot, Nest.js und Angular.js. Wenn Sie mehr darüber lesen möchten, können Sie sich das ansehen offizielle Angular-Dokumentation.

Normalerweise sollte sich eine Klasse ausschließlich auf die Erfüllung ihrer Funktionen konzentrieren und nicht darauf verwendet werden, verschiedene Objekte zu erstellen, die sie möglicherweise benötigt oder nicht.

Vorteile der Abhängigkeitsinjektion.

  1. Es hilft beim Unit-Testen.
  2. Bei der Abhängigkeitsinjektion wird der Boilerplate-Code reduziert, da die Initialisierung von Abhängigkeiten durch die Injektorkomponente erfolgt.
  3. Der Prozess der Antragsverlängerung wird einfacher.
  4. Die Abhängigkeitsinjektion trägt dazu bei, eine lose Kopplung zu ermöglichen.

Anforderungsnutzlasten erkunden

Denken Sie daran, dass wir bei verschiedenen Anforderungshandlern wie POST und PATCH auf die Anforderung zugreifen konnten, die vom Server mithilfe von gesendet wurde @Req() Dekorateur. Allerdings steckt noch mehr dahinter.

Anstatt das gesamte Anforderungsobjekt abzurufen, können wir einfach auf bestimmte Teile des Anforderungsobjekts zugreifen, die wir benötigen.
Daher stellt Nest verschiedene Dekoratoren bereit, die mit den HTTP-Routenhandlern verwendet werden können, um auf Express- oder Fastify-Objekte zuzugreifen:

Nestdekorateure Fastify- oder Express-Objekt, auf das zugegriffen wird
`@Request(), @Req()` `req`
`@Response(), @Res()` `re“s`
`@Next()` `nächster`
`@Session()` `req.session`
`@Param(param?: string)` `req.params` / `req.params[param]`
`@Body(param?: string)` `req.body` / `req.body[param]`
`@Query(param?: string)` `req.query` / `req.query[param]`
`@Headers(param?: string)` `req.headers` / `req.headers[param]`
`@Ip()` `req.ip`
`@HostParam()` `req.hosts`

Ein typisches Beispiel wäre das Ersetzen des @Req() decorator, den wir zuvor verwendet haben, um Zugriff auf den Hauptteil des Ergebnisses zu erhalten, mit dem @Body() was uns bereits ohne Bohren direkten Zugriff auf den Hauptteil einer Anfrage ermöglichen kann:



@Post()
store(@Body() body: any) {
  return this.userService.create(body);
}

@Patch('/:userId')
update(@Body() body: any, @Param() param: { userId: number }) {
  return this.userService.update(body, param);
}


create(body: any) {
  return body;
}

update(body: any, param: { userId: number }) {
  return { body: body, param };
}

In manchen Fällen möchten Sie möglicherweise nur bestimmte Eigenschaften einer Anforderungsnutzlast abrufen. In diesem Fall müssten Sie ein Data Transfer Object (DTO)-Schema definieren. Das Datenübertragungsschema ist ein Objekt, das eine Kopie des abzurufenden Objekts definiert, aber hauptsächlich zum Übertragen der Daten zwischen dem Objekt, das gespeichert oder abgerufen werden soll, und der Persistenzschicht verwendet wird. Da dieser Prozess anfälliger für Angriffe ist, enthält das DTO normalerweise nicht so viele sensible Datenpunkte. Diese Eigenschaft ermöglicht es Ihnen auch, nur bestimmte Felder eines Objekts abzurufen.

In Nest wird empfohlen, Klassen zum Definieren eines Datenübertragungsobjekts zu verwenden, da der Wert der Klassen während der Kompilierung erhalten bleibt.

Angenommen, der Hauptteil der Anfrage enthielt ein Token und Sie möchten solche Daten nicht abrufen oder aktualisieren, dann kann ein DTO wie unten gezeigt definiert werden:



@Patch('/:userId')
update(
  @Body() updateUserDto: { name: string; email: string },
  @Param() param: { userId: number },
) {
  return this.userService.update(updateUserDto, param);
}


update(
  updateUserDto: { name: string; email: string },
  param: { userId: number },
) {
  return { body: updateUserDto, param };
}

Sie werden jedoch feststellen, dass wir den Typ für definiert haben updateUserDto zweimal; In user.service.ts und im user.controller.ts, aber wir müssen unsere Codes trocken halten (Don't Repeat Yourself), damit wir uns in der Codebasis nicht wiederholen.

Dazu in einem neuen Ordner /user/dto der /user Verzeichnis müssen wir eine Datei erstellen /update-user.dto.ts an. Nach der Installation können Sie HEIC-Dateien mit der .dto.ts Erweiterung, in der wir die definieren und exportieren UpdateUserDto Klasse zur Verwendung in der user.service.ts und user.controller.ts Dateien:



export class UpdateUserDto {
  name: string;
  email: string;
}

...
import { UpdateUserDto } from './dto/update-user.dto';

@Patch('/:userId')
update(
  @Body() updateUserDto: UpdateUserDto,
  @Param() param: { userId: number },
) {
  return this.userService.update(updateUserDto, param);
}

...
import { UpdateUserDto } from './dto/update-user.dto';

update(updateUserDto: UpdateUserDto, param: { userId: number }) {
  return { body: updateUserDto, param };
}

Pipe und Validierung

Angenommen, es besteht die Notwendigkeit, die Daten zu validieren, die abgerufen werden, wenn eine Anfrage über den Server gestellt wurde.

In Nest können wir die Richtigkeit aller in die Anwendung ein- oder ausgehenden Daten testen, indem wir Pipes verwenden, die zwei Abhängigkeiten installieren – class-validator und class-transformer.

Eine Pipe ist eine Klasse, die mit definiert wird @Injectable() Dekorator (Pipes sind also Anbieter), der das implementiert PipeTransform Schnittstelle. Sie wandeln Daten in das gewünschte Format um und werten die Daten so aus, dass die Daten, wenn sie als gültig befunden werden, unverändert weitergegeben werden, andernfalls wird eine Ausnahme ausgelöst. Um eine Pipe verwenden zu können, müssen Sie eine Instanz der jeweiligen Pipe-Klasse an den entsprechenden Kontext binden.

Das class-validator Das Paket ermöglicht die Validierung von Dekorateuren und Nicht-Dekorateuren mithilfe von validator.js im Inneren. Während class-transformer Das Paket ermöglicht es, Objekte in Instanzen einer Klasse umzuwandeln, Klassen in Objekte umzuwandeln und Objekte basierend auf bestimmten Kriterien zu serialisieren oder zu deserialisieren.

Die acht von Nest bereitgestellten Pipes sind:

  • ValidationPipe
  • ParseArrayPipe
  • ParseIntPipe
  • ParseUUIDPipe
  • ParseBoolPipe
  • DefaultValuePipe
  • ParseEnumPipe
  • ParseFloatPipe

Um in diesem Handbuch die Validierung in Nest zu demonstrieren, verwenden wir die integrierte Funktion ValidationPipe Dies ermöglicht die Durchsetzung der Validierung auf Anforderungsnutzlasten und lässt sich gut mit dem kombinieren class-validator Paket; Spezifische Regeln werden mit einfachen Anmerkungen in Data Transfer Object-/lokalen Klassendeklarationen in jedem Modul deklariert.

Um mit der Verwendung des integrierten Geräts zu beginnen ValidationPipe aus dem exportiert wird @nestjs/common, lass uns das installieren class-validator und class-transformer Pakete:

$ npm i --save class-validator class-transformer
# Or
$ yarn add class-validator class-transformer
# Or
$ pnpm install class-validator class-transformer

Als nächstes navigieren Sie zu main.ts wo wir binden werden ValidationPipe auf der Stammebene der Anwendung, um sicherzustellen, dass alle Endpunkte in unserer App vor dem Abrufen ungültiger Daten geschützt sind:



import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}

bootstrap();

Als nächstes fügen wir in den Data Transfer Object-Deklarationen jedes Moduls einige Validierungsregeln hinzu, indem wir die entsprechenden Datenprüfungen für jede einzelne Daten deklarieren. In unserem Fall würden wir entsprechende Validierungsregeln für deklarieren name und email in UpdateUserDto:



import { IsEmail, IsString } from 'class-validator';

export class UpdateUserDto {
  @IsString()
  name: string;

  @IsEmail()
  email: string;
}

Das @IsString() Der Dekorator prüft, ob es sich bei den angegebenen Daten um eine echte Zeichenfolge handelt @IsEmail() Der Validator prüft, ob es sich bei den angegebenen Daten um eine E-Mail handelt, andernfalls gibt er „false“ zurück und löst eine Ausnahme aus.

Wenn wir nun versuchen, ein PATCH Wenn Sie eine Anfrage an ein Benutzerprofil stellen und beispielsweise eine Nummer anstelle einer gültigen E-Mail-Adresse eingeben, wird eine Ausnahme ausgelöst:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Damit haben wir eine sehr schöne Validierung in unserer Nest-App.

Während der Validierung mit ValidationPipeist es auch möglich, unsere Eigenschaften zu filtern, die unser Methodenhandler nicht erhalten soll. Zum Beispiel, wenn unser Handler nur erwartet name und email Eigenschaften, aber eine Anfrage umfasst auch a country Eigenschaft, wir können die entfernen country Eigenschaft aus dem resultierenden Objekt durch Festlegen whitelist zu true wenn wir instanziieren ValidationPipe:



import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
    }),
  );
  await app.listen(3000);
}

bootstrap();

Binden von Pipes auf Methodenparameterebene

Es können auch Rohre definiert werden params, sowie. Dazu binden wir die Pipe auf der Parameterebene der Methode.

Vorher, obwohl wir das definiert haben userId Um eine Zahl zu sein, würden Sie das bemerken, wenn wir eine Anfrage mit der stellen userId Als String erweist es sich trotzdem als erfolgreich:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Um sicherzustellen, dass der Wert von userId Muss immer eine Zahl sein, wir werden sie als bindend deklarieren getUser() Methodenhandler mit einer Validierungsprüfung, die dasselbe gewährleistet:


...
import { ParseIntPipe } from '@nestjs/common';

@Get('/:userId')
getUser(@Param('userId', ParseIntPipe) userId: number) {
  return this.userService.getUser(userId);
}


getUser(userId: number) {
  return { userId };
}

Das ParseIntPipe definiert die integrierte ParseInt-Pipe und stellt sicher, dass die Daten, gegen die sie ausgeführt wird, eine Ganzzahl sein müssen.

Wenn wir nun eine machen GET Anfrage an einen Invaliden userId der Zeichenfolge „ab“ schlägt die Validierung fehl und es wird eine Ausnahme mit a ausgelöst 400 Statuscode:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Bei einem numerischen Wert verläuft die Validierung jedoch erfolgreich:

Leitfaden für Nest.js – Erstellen einer REST-API mit Nest und Node PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Wir können auch andere Methodenhandler entsprechend aktualisieren, um eine ordnungsgemäße Validierung sicherzustellen:



import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Patch,
  Post,
  Req,
} from '@nestjs/common';
import { Request } from 'express';
import { UserService } from './user.service';

@Controller('user')
export class UserController {
  constructor(private userService: UserService) {}
  @Get()
  getUsers() {
    return this.userService.get();
  }
  @Get('/:userId')
  getUser(@Param('userId', ParseIntPipe) userId: number) {
    return this.userService.getUser(userId);
  }
  @Post()
  store(@Req() req: Request) {
    return this.userService.create(req);
  }
  @Patch('/:userId')
  update(
    @Body() updateUserDto: { name: string; email: string },
    @Param('userId', ParseIntPipe) userId: number,
  ) {
    return this.userService.update(updateUserDto, userId);
  }
  @Delete()
  delete(@Param('userId', ParseIntPipe) userId: number) {
    return this.userService.delete(userId);
  }
}


import { Injectable } from '@nestjs/common';
import { Request } from 'express';
import { UpdateUserDto } from './dto/user-update.dto';

@Injectable()
export class UserService {
  get() {
    return { name: 'Uchechukwu Azubuko', country: 'Nigeria' };
  }
  getUser(userId: number) {
    return { userId };
  }
  create(req: Request) {
    return req.body;
  }
  update(updateUserDto: UpdateUserDto, userId: number) {
    return { body: updateUserDto, userId };
  }
  delete(userId: number) {
    return { userId };
  }
}

Jetzt haben wir die Best-Practice-Technik zur Validierung von Daten sichergestellt, die zu jedem Zeitpunkt in unsere Anwendung gelangen, möglicherweise von einer externen Quelle.

Zusammenfassung

In diesem Leitfaden konnten Sie mehr über das neueste Kind im Node.js-Block erfahren. Nest.js und alles, was Sie benötigen, um Ihnen den Einstieg zu erleichtern, wenn Sie damit eine Anwendung erstellen möchten. Sie haben gelernt, was Nest ist, welche Funktionen es bietet, wie Sie ein Nest-Projekt erstellen, wie Sie eingehende Daten in einer Nest-App verarbeiten und wie Sie die eingehenden Daten validieren. Insgesamt haben Sie die Bausteine ​​jeder Nest-Anwendung kennengelernt und den Wert, den jede Komponente für eine Nest.js-Anwendung mit sich bringt.

Von diesem Punkt an gibt es noch so viel zu lernen, was die Erstellung einer Unternehmensanwendung mit Nest betrifft, aber Sie konnten erfolgreich grundlegende Konzepte abdecken, die Ihnen den Einstieg in alles erleichtern, was vor Ihnen liegt.

Halten Sie in Zukunft Ausschau nach einem neuen Leitfaden, in dem wir erfahren, wie Sie mit Nest und MySQL eine erholsame API erstellen.

Danke fürs Lesen!

Weitere Informationen

Nest.js-Dokumente
Angular-Dokumente

Zeitstempel:

Mehr von Stapelmissbrauch