Full-Stack-TypeScript-Apps

Hallo Habr! Ich präsentiere Ihnen die Übersetzung des Artikels "Full-Stack TypeScript Apps - Teil 1: Entwickeln von Backend-APIs mit Nest.js" von Ana Ribeiro .


Teil 1: Entwickeln der Server-API mit Nest.JS


TL; DR: Dies ist eine Reihe von Artikeln zum Erstellen einer TypeScript-Webanwendung mit Angular und Nest.JS. Im ersten Teil werden wir eine einfache Server-API mit Nest.JS schreiben. Der zweite Teil dieser Serie ist der Front-End-Anwendung mit Angular gewidmet. Den endgültigen Code, der in diesem Artikel entwickelt wurde, finden Sie in diesem GitHub-Repository.


Was ist Nest.Js und warum Angular?


Nest.js ist ein Framework zum Erstellen von Node.js Webserveranwendungen.


Eine Besonderheit ist, dass es ein Problem löst, das kein anderes Framework löst: die Struktur des node.js-Projekts. Wenn Sie jemals unter node.js entwickelt haben, wissen Sie, dass Sie mit einem Modul viel erreichen können (z. B. kann Express Middleware alles von der Authentifizierung bis zur Validierung erledigen), was letztendlich zu einem nicht unterstützten "Durcheinander" führen kann. . Wie Sie unten sehen werden, hilft uns nest.js dabei, indem es Klassen bereitstellt, die sich auf verschiedene Themen spezialisiert haben.


Nest.js ist stark von Angular inspiriert. Zum Beispiel Beide Plattformen verwenden Schutzvorrichtungen, um den Zugriff auf einige Teile Ihrer Anwendungen zu ermöglichen oder zu verhindern, und beide Plattformen bieten eine CanActivate-Schnittstelle zum Implementieren dieser Schutzfunktionen. Es ist jedoch wichtig zu beachten, dass trotz einiger ähnlicher Konzepte beide Strukturen unabhängig voneinander sind. Das heißt, in diesem Artikel erstellen wir eine unabhängige API für unser Front-End, die mit jedem anderen Framework (React, Vue.JS usw.) verwendet werden kann.


Webanwendung für Online-Bestellungen


In diesem Handbuch erstellen wir eine einfache Anwendung, in der Benutzer Bestellungen in einem Restaurant aufgeben können. Diese Logik wird implementiert:


  • Jeder Benutzer kann das Menü anzeigen.
  • Nur ein autorisierter Benutzer kann Waren in den Warenkorb legen (Bestellung aufgeben).
  • Nur der Administrator kann neue Menüelemente hinzufügen.

Der Einfachheit halber werden wir nicht mit einer externen Datenbank interagieren und die Funktionalität unseres Warenkorbs nicht implementieren.


Erstellen der Dateistruktur des Nest.js-Projekts


Um Nest.js zu installieren, müssen wir Node.js (v.8.9.x oder höher) und NPM installieren. Laden Sie Node.js für Ihr Betriebssystem von der offiziellen Website herunter und installieren Sie es (NPM ist enthalten). Wenn alles installiert ist, überprüfen Sie die Versionen:


node -v # v12.11.1 npm -v # 6.11.3 

Es gibt verschiedene Möglichkeiten, ein Projekt mit Nest.js zu erstellen. Sie finden sie in der Dokumentation . Wir werden nest-cli . Installieren Sie es:


npm i -g @nestjs/cli


Als nächstes erstellen Sie unser Projekt mit einem einfachen Befehl:


nest new nest-restaurant-api


Dabei werden wir von nest aufgefordert, einen Paketmanager auszuwählen: npm oder yarn


Wenn alles gut gegangen ist, erstellt nest die folgende Dateistruktur:


 nest-restaurant-api ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── .gitignore ├── .prettierrc ├── nest-cli.json ├── package.json ├── package-lock.json ├── README.md ├── tsconfig.build.json ├── tsconfig.json └── tslint.json 

Wechseln Sie in das erstellte Verzeichnis und starten Sie den Entwicklungsserver:


  #    cd nest-restaurant-api #   npm run start:dev 

Öffnen Sie einen Browser und geben Sie http://localhost:3000 . Auf dem Bildschirm sehen wir:


Im Rahmen dieses Tutorials werden wir unsere API nicht testen (obwohl Sie Tests für jede gebrauchsfertige Anwendung schreiben sollten). Auf diese Weise können Sie das src/app.controller.spec.ts löschen und die src/app.controller.spec.ts (die Testdatei) löschen. Daher enthält unser Quellordner die folgenden Dateien:


  • src/app.controller.ts und src/app.module.ts : Diese Dateien sind für die Erstellung der Hello world Nachricht entlang der / route verantwortlich. Weil Dieser Einstiegspunkt ist für diese Anwendung nicht wichtig. Wir löschen sie. In Kürze werden Sie detaillierter erfahren, was Controller und Services sind .
  • src/app.module.ts : enthält eine Beschreibung einer Klasse von src/app.module.ts , die für die Deklaration des Imports, Exports von Controllern und Anbietern in die Anwendung nest.js verantwortlich ist. Jede Anwendung verfügt über mindestens ein Modul. Sie können jedoch mehr als ein Modul für komplexere Anwendungen erstellen (mehr in der Dokumentation . Unsere Anwendung enthält nur ein Modul
  • src/main.ts : Dies ist die Datei, die für den Start des Servers verantwortlich ist.

Hinweis: Nach dem Entfernen von src/app.controller.ts und src/app.module.ts Sie unsere Anwendung nicht starten. Keine Sorge, wir werden es bald beheben.

Einstiegspunkte erstellen (Endpunkte)



Unsere API wird auf der Route /items verfügbar sein. Über diesen Einstiegspunkt können Benutzer Daten empfangen und Administratoren verwalten das Menü. Lass es uns schaffen.


Erstellen Sie dazu ein Verzeichnis mit dem Namen items in src . Alle Dateien, die der Route /items sind, werden in diesem neuen Verzeichnis gespeichert.


Controller erstellen


In nest.js sind Controller wie in vielen anderen Frameworks für die Zuordnung von Routen mit Funktionen verantwortlich. nest.js zum Erstellen eines Controllers in nest.js den nest.js Dekorator wie folgt: @Controller(${ENDPOINT}) . Um verschiedene HTTP Methoden wie GET und POST @Get , werden @Post Dekoratoren @Get , @Post , @Delete usw. verwendet.


In unserem Fall müssen wir einen Controller erstellen, der die im Restaurant verfügbaren Gerichte zurückgibt und mit dem Administratoren den Inhalt des Menüs verwalten. Erstellen wir eine Datei mit dem Namen items.controller.tc im Verzeichnis src/items mit den folgenden Inhalten:


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController { @Get() async findAll(): Promise<string[]> { return ['Pizza', 'Coke']; } @Post() async create() { return 'Not yet implemented'; } } 

Um unseren neuen Controller in unserer Anwendung verfügbar zu machen, registrieren Sie ihn im Modul:


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; @Module({ imports: [], controllers: [ItemsController], providers: [], }) export class AppModule {} 

Starten Sie unsere Anwendung: npm run start:dev und öffnen Sie sie im Browser http: // localhost: 3000 / items . Wenn Sie alles richtig gemacht haben, sollten wir die Antwort auf unsere Get-Anfrage sehen: ['Pizza', 'Coke'] .


Anmerkung des nest.js : nest.js neue Controller sowie andere Elemente von nest.js : Dienste, Anbieter usw., ist es bequemer, den Befehl nest generate aus dem nest-cli . Um beispielsweise den oben beschriebenen Controller zu erstellen, können Sie den Befehl nest generate controller items Infolgedessen erstellt src/items/items.controller.tc src/items/items.controller.spec.tc und src/items/items.controller.tc folgenden Inhalten:


  import { Get, Post, Controller } from '@nestjs/common'; @Controller('items') export class ItemsController {} 

und registrieren Sie es in app.molule.tc


Hinzufügen eines Dienstes


Beim Zugriff auf /items unsere Anwendung jetzt für jede Anforderung dasselbe Array zurück, das wir nicht ändern können. Das Verarbeiten und Speichern von Daten ist nicht Sache des Controllers. Zu diesem Zweck sind Dienste in nest.js vorgesehen
Dienste im Nest sind @Injectable
Der Name des Dekorateurs spricht für sich selbst. Durch Hinzufügen dieses Dekorators zur Klasse kann er in andere Komponenten wie z. B. Controller injiziert werden.
Lassen Sie uns unseren Service erstellen. Erstellen Sie die Datei items.service.ts Ordner items.service.ts mit den folgenden Inhalten:


  import { Injectable } from '@nestjs/common'; @Injectable() export class ItemsService { private readonly items: string[] = ['Pizza', 'Coke']; findAll(): string[] { return this.items; } create(item: string) { this.items.push(item); } } 

und ändern Sie den ItemsController Controller (deklariert in items.controller.ts ), um unseren Service zu nutzen:


  import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<string[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: string) { this.itemsService.create(item); } } 

In der neuen Version des Controllers haben wir den @Body Dekorator auf das Argument create method angewendet. Dieses Argument wird verwendet, um die über req.body ['item'] Daten automatisch mit dem Argument selbst (in diesem Fall item ) req.body ['item'] .
Außerdem empfängt unser Controller eine Instanz der ItemsService Klasse, die über den Konstruktor ItemsService wird. Wenn Sie ItemsService als private readonly wird eine Instanz unveränderlich und nur innerhalb der Klasse sichtbar.
Und vergessen Sie nicht, unseren Service in app.module.ts zu registrieren:


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController], providers: [ItemsService], }) export class AppModule {} 

Senden Sie nach allen Änderungen eine HTTP-POST-Anfrage an das Menü:


  curl -X POST -H 'content-type: application/json' -d '{"item": "Salad"}' localhost:3000/items 

Anschließend überprüfen wir, ob neue Gerichte auf unserer Speisekarte erscheinen, indem wir eine GET-Anfrage stellen (oder indem wir http: // localhost: 3000 / items in einem Browser öffnen).


  curl localhost:3000/items 

Erstellen einer Warenkorbroute


Nachdem wir die erste Version des Einstiegspunkts /items unserer API haben, implementieren wir die Warenkorbfunktion. Der Prozess zum Erstellen dieser Funktionalität unterscheidet sich nicht wesentlich von der bereits erstellten API. Um das Handbuch nicht zu überladen, erstellen wir eine Komponente, die beim Zugriff mit dem Status OK antwortet.


Erstellen Sie zunächst im shoping-cart.controller.ts :


  import { Post, Controller } from '@nestjs/common'; @Controller('shopping-cart') export class ShoppingCartController { @Post() async addItem() { return 'This is a fake service :D'; } } 

Registrieren Sie diesen Controller in unserem Modul ( app.module.ts ):


  import { Module } from '@nestjs/common'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule {} 

Führen Sie den folgenden Befehl aus, um diesen Einstiegspunkt zu überprüfen, nachdem Sie sichergestellt haben, dass die Anwendung ausgeführt wird:


  curl -X POST localhost:3000/shopping-cart 

Hinzufügen eines Schnittstellentypskripts für Elemente


Zurück zu unserem items . Jetzt speichern wir nur den Namen des Gerichts, aber dies ist eindeutig nicht genug, und wir werden sicher mehr Informationen haben wollen (zum Beispiel die Kosten des Gerichts). Ich denke, Sie werden zustimmen, dass das Speichern dieser Daten als Array von Zeichenfolgen keine gute Idee ist?
Um dieses Problem zu lösen, können wir ein Array von Objekten erstellen. Aber wie kann man die Struktur von Objekten speichern? Hier hilft uns die TypeScript-Oberfläche, in der wir die Struktur des items Objekts definieren. Erstellen Sie eine neue Datei mit dem Namen item.interface.ts im Ordner src/items :


  export interface Items { readonly name: string; readonly price: number; } 

items.service.ts Datei items.service.ts :


 import { Injectable } from '@nestjs/common'; import { Item } from './item.interface'; @Injectable() export class ItemsService { private readonly items: Item[] = []; findAll(): Item[] { return this.items; } create(item: Item) { this.items.push(item); } } 

Und auch in items.controller.ts :


 import { Get, Post, Body, Controller } from '@nestjs/common'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() async create(@Body() item: Item) { this.itemsService.create(item); } } 

Validierung der Eingabe in Nest.js


Trotz der Tatsache, dass wir die Struktur des item , gibt unsere Anwendung keinen Fehler zurück, wenn wir eine ungültige POST-Anforderung senden (alle Arten von Daten, die nicht in der Schnittstelle definiert sind). Zum Beispiel für eine solche Anfrage:


  curl -H 'Content-Type: application/json' -d '{ "name": 3, "price": "any" }' http://localhost:3000/items 

Der Server sollte mit einem Status von 400 (fehlerhafte Anfrage) antworten. Stattdessen antwortet unsere Anwendung mit einem Status von 200 (OK).


Um dieses Problem zu lösen, erstellen Sie ein DTO (Data Transfer Object) und eine Pipe-Komponente (Channel).


DTO ist ein Objekt, das definiert, wie Daten zwischen Prozessen übertragen werden sollen. Wir beschreiben das DTO in der src/items/create-item.dto.ts :


  import { IsString, IsInt } from 'class-validator'; export class CreateItemDto { @IsString() readonly name: string; @IsInt() readonly price: number; } 

Pipes in Nest.js sind die Komponenten, die für die Validierung verwendet werden. Erstellen Sie für unsere API einen Kanal, in dem überprüft wird, ob die an die Methode gesendeten Daten mit dem DTO übereinstimmen. Ein Kanal kann von verschiedenen Controllern verwendet werden. Erstellen Sie daher das Verzeichnis src/common/ mit der Datei validation.pipe.ts :


  import { ArgumentMetadata, BadRequestException, Injectable, PipeTransform, } from '@nestjs/common'; import { validate } from 'class-validator'; import { plainToClass } from 'class-transformer'; @Injectable() export class ValidationPipe implements PipeTransform<any> { async transform(value, metadata: ArgumentMetadata) { const { metatype } = metadata; if (!metatype || !this.toValidate(metatype)) { return value; } const object = plainToClass(metatype, value); const errors = await validate(object); if (errors.length > 0) { throw new BadRequestException('Validation failed'); } return value; } private toValidate(metatype): boolean { const types = [String, Boolean, Number, Array, Object]; return !types.find(type => metatype === type); } } 

Hinweis: Wir müssen zwei Module installieren: class-validator und class-transformer . Führen Sie dazu npm install class-validator class-transformer in der Konsole aus und starten Sie den Server neu.

Anpassen von items.controller.ts für die Verwendung mit unserer neuen Pipe und DTO:


  import { Get, Post, Body, Controller, UsePipes } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

Lassen Sie uns unseren Code noch einmal überprüfen. Jetzt akzeptiert der Eintrag /items nur dann Daten, wenn sie im DTO definiert sind. Zum Beispiel:


  curl -H 'Content-Type: application/json' -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

Fügen Sie ungültige Daten ein (Daten, die in ValidationPipe nicht überprüft werden können). Als Ergebnis erhalten wir die Antwort:


  {"statusCode":400,"error":"Bad Request","message":"Validation failed"} 

Middleware erstellen

Laut der Auth0-Schnellstartanleitung wird empfohlen, das von Auth0 ausgegebene JWT-Token zu überprüfen, indem Sie die von express-jwt bereitgestellte express-jwt . Diese Middleware automatisiert einen großen Teil der Arbeit.


Erstellen wir eine authentication.middleware.ts Datei im Verzeichnis src / common mit dem folgenden Code:


  import { NestMiddleware } from '@nestjs/common'; import * as jwt from 'express-jwt'; import { expressJwtSecret } from 'jwks-rsa'; export class AuthenticationMiddleware implements NestMiddleware { use(req, res, next) { jwt({ secret: expressJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: 'https://${DOMAIN}/.well-known/jwks.json', }), audience: 'http://localhost:3000', issuer: 'https://${DOMAIN}/', algorithm: 'RS256', })(req, res, err => { if (err) { const status = err.status || 500; const message = err.message || 'Sorry, we were unable to process your request.'; return res.status(status).send({ message, }); } next(); }); }; } 

Ersetzen Sie ${DOMAIN} durch den Domänenwert aus den Auth0-Anwendungseinstellungen


Anmerkung des Übersetzers: DOMAIN Sie in einer realen Anwendung DOMAIN in eine Konstante und legen Sie den Wert über env (virtuelle Umgebung) fest.

Installieren Sie die jwks-rsa express-jwt und jwks-rsa :


  npm install express-jwt jwks-rsa 

Es ist notwendig, die erstellte Middleware (Handler) mit unserer Anwendung zu verbinden. Dazu in der Datei ./src/app.module.ts :


  import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { AuthenticationMiddleware } from './common/authentication.middleware'; import { ItemsController } from './items/items.controller'; import { ShoppingCartController } from './shopping-cart/shopping-cart.controller'; import { ItemsService } from './items/items.service'; @Module({ imports: [], controllers: [ItemsController, ShoppingCartController], providers: [ItemsService], }) export class AppModule { public configure(consumer: MiddlewareConsumer) { consumer .apply(AuthenticationMiddleware) .forRoutes( { path: '/items', method: RequestMethod.POST }, { path: '/shopping-cart', method: RequestMethod.POST }, ); } } 

Der obige Code besagt, dass POST-Anforderungen an die Routen /items und /shopping-cart durch Express-Middleware geschützt sind, die in der Anforderung nach dem Zugriffstoken sucht.


Starten Sie den Entwicklungsserver neu ( npm run start:dev ) und rufen Sie die Nest.js-API auf:


  #     curl -X POST http://localhost:3000/shopping-cart #      TOKEN="eyJ0eXAiO...Mh0dpeNpg" # and issue a POST request with it curl -X POST -H 'authorization: Bearer '$TOKEN http://localhost:3000/shopping-cart 

Rollenverwaltung mit Auth0

Derzeit kann jeder Benutzer mit einem verifizierten Token Elemente in unserer API veröffentlichen. Wir möchten jedoch, dass dies nur Benutzer mit Administratorrechten tun können. Um diese Funktion zu implementieren, verwenden wir die Regeln (Regeln) Auth0 .


Wechseln Sie also zur Systemsteuerung Auth0 im Abschnitt Regeln . Klicken Sie dort auf die + CREATE RULE und wählen Sie als Regelmodell "Rollen für einen Benutzer + CREATE RULE ".



Anschließend erhalten wir eine JavaScript-Datei mit einer Regelvorlage, die jedem Benutzer, der E-Mails hat, die zu einer bestimmten Domäne gehören, die Administratorrolle hinzufügt. Lassen Sie uns einige Details in dieser Vorlage ändern, um ein Funktionsbeispiel zu erhalten. Für unsere Anwendung gewähren wir dem Administrator nur Zugriff auf unsere eigene E-Mail-Adresse. Wir müssen auch den Speicherort für die Speicherung von Administratorstatusinformationen ändern.


Derzeit werden diese Informationen in einem Identifikationstoken gespeichert (das zum Bereitstellen von Informationen über den Benutzer verwendet wird). Für den Zugriff auf Ressourcen in der API sollte jedoch ein Zugriffstoken verwendet werden. Der Code nach den Änderungen sollte folgendermaßen aussehen:


  function (user, context, callback) { user.app_metadata = user.app_metadata || {}; if (user.email && user.email === '${YOUR_EMAIL}') { user.app_metadata.roles = ['admin']; } else { user.app_metadata.roles = ['user']; } auth0.users .updateAppMetadata(user.user_id, user.app_metadata) .then(function() { context.accessToken['http://localhost:3000/roles'] = user.app_metadata.roles; callback(null, user, context); }) .catch(function(err) { callback(err); }); } 

Hinweis: Ersetzen Sie ${YOUR_EMAIL} durch Ihre E-Mail-Adresse. Es ist wichtig zu beachten, dass es in der Regel ideal ist, die E-Mail-Überprüfung zu erzwingen , wenn Sie mit E-Mails in den Auth0-Regeln arbeiten. In diesem Fall ist dies nicht erforderlich, da wir unsere eigene E-Mail-Adresse verwenden.

Anmerkung des Übersetzers: Das obige Codefragment wird im Browser auf der Konfigurationsseite der Auth0-Regel eingegeben

Um zu überprüfen, ob das an unsere API übergebene Token das Administrator-Token ist, müssen wir einen Schutz Nest.js erstellen. Erstellen Sie im Ordner src/common die Datei admin.guard.ts


  import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AdminGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const user = context.getArgs()[0].user['http://localhost:3000/roles'] || ''; return user.indexOf('admin') > -1; } } 

Wenn wir nun den oben beschriebenen Anmeldevorgang wiederholen und die in der Regel definierte E-Mail-Adresse verwenden, erhalten wir ein neues access_token . Um den Inhalt dieses access_token zu überprüfen, kopieren Sie das Token und fügen Sie es in das Feld Encoded der Site https://jwt.io/ . Wir werden sehen, dass der Payload-Abschnitt dieses Tokens das folgende Array enthält:


  "http://localhost:3000/roles": [ "admin" ] 

Wenn unser Token diese Informationen wirklich enthält, setzen wir die Integration mit Auth0 fort. Öffnen Sie also items.controller.ts und fügen Sie dort unseren neuen Wächter hinzu:


  import { Get, Post, Body, Controller, UsePipes, UseGuards, } from '@nestjs/common'; import { CreateItemDto } from './create-item.dto'; import { ItemsService } from './items.service'; import { Item } from './item.interface'; import { ValidationPipe } from '../common/validation.pipe'; import { AdminGuard } from '../common/admin.guard'; @Controller('items') export class ItemsController { constructor(private readonly itemsService: ItemsService) {} @Get() async findAll(): Promise<Item[]> { return this.itemsService.findAll(); } @Post() @UseGuards(new AdminGuard()) @UsePipes(new ValidationPipe()) async create(@Body() createItemDto: CreateItemDto) { this.itemsService.create(createItemDto); } } 

Mit unserem neuen Token können wir jetzt neue Elemente über unsere API hinzufügen:


  #    npm run start:dev #  POST       curl -X POST -H 'Content-Type: application/json' \ -H 'authorization: Bearer '$TOKEN -d '{ "name": "Salad", "price": 3 }' http://localhost:3000/items 

Anmerkung des Übersetzers: Zur Überprüfung können Sie sehen, was wir in den Artikeln haben:
 curl -X GET http://localhost:3000/items 


Zusammenfassung


Glückwunsch! Wir haben gerade die Erstellung unserer Nest.JS-API abgeschlossen und können uns nun auf die Entwicklung des Frontend-Teils unserer Anwendung konzentrieren! Lesen Sie unbedingt den zweiten Teil dieser Serie: Full-Stack TypeScript-Apps - Teil 2: Entwickeln von Frontend Angular Apps.


Anmerkung des Übersetzers: Die Übersetzung des zweiten Teils des Prozesses

Zusammenfassend haben wir in diesem Artikel verschiedene Funktionen von Nest.js und TypeScript verwendet: Module, Controller, Dienste, Schnittstellen, Pipes, Middleware und Guard zum Erstellen API Ich hoffe, Sie haben gute Erfahrungen gemacht und sind bereit, unsere Anwendung weiterzuentwickeln. Wenn Ihnen etwas nicht klar ist, ist die offizielle Dokumentation zu nest.j eine gute Quelle mit Antworten

Source: https://habr.com/ru/post/de471348/


All Articles