Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Veiledning til Nest.js – Bygg et REST API med Nest og Node

Som en Node.js backend-utvikler vil du være enig i at Node.js som standard er veldig bare bein, og gjør ingen antagelser om hva du trenger mens du bygger en app. Som et resultat er du ansvarlig for å sette opp alt du vil bruke på tvers av en app, inkludert håndtering av ruting, foreta API-anrop, sette opp TypeScript eller Web Sockets, eller til og med grunnleggende ting som kodeorganisering, filstruktur og navnekonvensjoner .

Å administrere en storstilt applikasjon kan være en vanskelig oppgave, spesielt hvis den ikke ble designet med en klar struktur og strenge retningslinjer for kodeorganisering.

Nest.js prøver å takle noen av disse problemene ved å lage en abstraksjon rundt Node.js slik at du som utvikler kan fokusere på applikasjonsproblemet i stedet for andre bittesmå implementeringsdetaljer.

I denne veiledningen vil du lære det grunnleggende om Nest.js fra topp til bunn, med sikte på å få deg oppdatert slik at du kan bygge enterprise-grade Node.js-applikasjoner ved hjelp av Nest.js på kort tid.

Alt vi vil lære gjennom denne veiledningen vil være inkrementell; dekker mye av introduksjonskonsepter. For å få mest mulig ut av denne veiledningen hjelper det å kode med.

La oss dykke rett inn, folkens!

Kildekode: Som vanlig kan du pusle med kildekoden som er vert på GitHub.

OBS: Vi bruker Postman til å teste API-en i demoen vår. Du kan laste den ned på Postman Last ned side. Alternativt kan du ganske enkelt bruke nettleseren, kommandolinjen curl verktøy, eller et annet verktøy du kanskje er kjent med.

Hva er Nest.js

Tenk på Nest.js som et supersett av Node.js som abstraherer bort vanskelige oppgaver, verktøy og standardkode, samtidig som du legger til et fullverdig verktøysett for applikasjonsutviklingen din ved hjelp av moderne JavaScript og TypeScript.

Nest.js gir en ut-av-boksen applikasjonsarkitektur som lar utviklere og team lage svært skalerbare, testbare, løst koblede og lett vedlikeholdbare, ved å utnytte lett tilgjengelige og fremtredende alternativer og moduler i fellesskapet, som de som er tilgjengelige i Express.js-applikasjoner. Du kan til og med bytte Express (som den bruker under panseret som standard) for Fastify, men å gjøre det vil bety at du kanskje må bruke forskjellige Fastify-kompatible biblioteker i applikasjonen din.

Den kombinerer funksjonene til funksjonell programmering, objektorientert programmering og funksjonell reaktiv programmering, og med mer enn 52.4k stjerner og 6.2k gafler på GitHub og et ukentlig nedlastingstall på opptil 1,784,004 XNUMX XNUMX, er det progressive Node.js-rammeverket et populært valg for å lage effektive, skalerbare og bedriftsbaserte serversideapplikasjoner.

Funksjoner i Nest.js

Følgende er grunner til at Nest.js har vokst til å bli et så populært Node.js-rammeverk:

  1. Nest.js ble opprettet for å hjelpe utviklere med å bygge både monolittiske applikasjoner og mikrotjenester også.
  2. Selv om den er kraftig, er den også utviklervennlig å jobbe med; enkel å bruke, rask å lære og enkel å bruke.
  3. Den utnytter TypeScript (et supersett av JavaScript) ut av esken og gir rom for utviklere til å skrive vedlikeholdbar kode uten kjøretidsfeil.
  4. Den har et kommandolinjegrensesnitt som bidrar til å øke produktiviteten til utviklere og enkel utvikling.
  5. Når du bygger med Nest.js, forbedres utviklingsprosessene og det spares tid enten du starter opp et minimum levedyktig produkt eller jobber med en applikasjon fordi Nest kommer med en fantastisk prosjektmappestruktur som standard.
  6. Den støtter en rekke Nest-spesifikke moduler som hjelper til med integrasjonen av vanlige konsepter og teknologier, inkludert TypeORM, GraphQL, logging, validering, Mongoose, WebSockets, caching, etc.
  7. Nest.js kan skryte av å ha noe av den beste dokumentasjonen for ethvert rammeverk der ute. Dokumentasjonen er grundig, lett å forstå og nyttig for å spare feilsøkingstid, siden den kommer gjennom uten problemer når det er behov for en løsning på et problem.
  8. Nest.js integreres med Jest, noe som gjør det enkelt å skrive enhetstester på applikasjonene dine.
  9. Den er bygget for både små og store bedriftsapplikasjoner.

Opprette et Nest.js-prosjekt

For å komme i gang med Nest.js på din lokale maskin, må du først installere Nest Command Line Interface (CLI), som vil bidra til å stillasere en ny Nest.js-prosjektmappe og fylle ut mappen med kjernefiler og moduler som trengs for en Nest.js-appen.

Kjør følgende kommando for å installere Nest.js kommandolinjegrensesnitt:

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

Når du har installert Nest.js CLI globalt på din lokale maskin, kan du kjøre nest på kommandolinjen for å se ulike kommandoer som vi kan bruke:

$ nest

Resulterer i:

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                 │
      └───────────────┴─────────────┴──────────────────────────────────────────────┘

Her får du vist hvordan du bruker kommandoene, og kan nå trykke på new|n [options] [name] kommando for å lage ditt aller første Nest.js-prosjekt:

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

Deretter vil du bli spurt om hvilken pakkebehandling du vil bruke:

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

Velg gjerne den pakkeforvalteren du ønsker, jeg går med pnpm. Dette er fordi det er omtrent tre ganger mer effektivt og raskere enn NPM, og med et hurtigbuffersystem er PNPM også raskere enn Yarn.

Etter å ha valgt en pakkebehandling, fortsetter installasjonsprosessen, og Nest.js-appen vil bli opprettet.

Nå kan du cd inn i det nyopprettede prosjektet, og åpne det med en editor du velger:

$ cd getting-started-with-nestjs

Med prosjektet nå opprettet, kan vi kjøre det med en av følgende kommandoer:

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

Hvis du tar en titt på package.json fil, vil du legge merke til i skriptsegmentet verdien for pnpm run start is nest start:


    
"start": "nest start",

Dette betyr at du også kan kjøre Nest.js-appen ved å kjøre:

$ nest start

En titt på Nest.js-prosjektstrukturen

La oss se nærmere på hvordan en Nest-app er strukturert:

/package.json

De package.json filen er hjertet av Node.js og ved utvidelse, Nest.js-prosjektet. Den inneholder alle metadata om prosjektet og definerer ulike funksjonelle egenskaper for prosjektet som er nødvendig for å installere applikasjonsavhengigheter eller kjøre prosjektskript.

Vi har allerede sett evnen til start skript.

De start:dev profilen gjør det mulig å se etter endringer i applikasjonen og automatisk laste den inn på nytt, uten å måtte stoppe applikasjonen og starte den på nytt – og den er ment for utvikling. De start:prod skriptet er nyttig når du vil teste om applikasjonen din er produksjonsklar, så vel som når du distribuerer den til produksjon, sammen med andre skript for å teste Nest.js-appen.

@nestjs/platform-express definerer express som standard HTTP-server i en Nest-applikasjon.

/tsconfig.json

De tsconfig.json fil er en fil skrevet i JSON (JavaScript Object Notation) som definerer TypeScript-relaterte alternativer som kreves for å kompilere Nest-appen.

/nest-cli.json

Dette inneholder metadata som er nødvendig for å bygge, organisere eller distribuere Nest-applikasjoner.

/test

Denne katalogen inneholder alle filene som trengs for å kjøre Nest-tester. Nest bruker Jest-rammeverket for testing med Jest-konfigurasjon i jest-e2e.json filen.

/src

De src katalogen er overordnet mappe for kjernen i Nest-prosjektet. Den holder main.ts fil som er filen der Nest-appen starter. Jobben til main.ts filen skal lastes AppModule som er importert fra /src/app.module.ts.

Senere i denne veiledningen vil vi lære om moduler; en av hovedkomponentene i en Nest.js-applikasjon.

De AppModule er en klasse som er opprettet som en modul ved å bruke @Module dekoratør. I app.module.ts fil, AppService fra ./app.service og AppController fra ./app.controller er også importert.

De AppController er også en klasse som er opprettet ved hjelp av @Controller dekoratør, mens AppService er en klasse som er opprettet ved hjelp av @Injectable merknad.

Det kule med Nest er at det har svært få dekoratører innen som legger til metadata til en hvilken som helst klasse, og at metadata definerer formålet med den klassen, slik at:

  • @Controller()forvandler en klasse til en kontroller.
  • @Module() forvandler en klasse til en modul.
  • @Injectable() forvandler en klasse til en leverandør.

Også i src katalogen er app.controller.spec.ts fil, som er en testfil for kontrollere.

Vi kan kjøre appen ved hjelp av nest start.

Appen starter kl http://localhost:3000 på nettleseren din:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Vi kan endre innholdet som vises kl http://localhost:3000, ved å gå over til app.service.ts fil, der leverandøren for indeksruten ble definert.

Byggesteinene til en Nest.js-app

Det er tre hovedkomponenter i en Nest.js-applikasjon:

  1. Moduler
  2. Controllers
  3. tilbydere

For å lære om byggesteinene til en Nest-app, la oss først rydde opp i Nest-prosjektet ved å slette app.controller.spec.ts, ./app.service, app.module.tsog ./app.controller filer; forlater bare main.ts, for å etterligne en utviklingslivssyklus fra bunnen av.

På dette tidspunktet, når vi fjerner den importerte AppModule fil fra main.ts, blir vi bedt om at et argument for 'modul' ikke ble gitt.

For å demonstrere byggesteinene til en Nest-app, vil vi ta en titt på en enkel brukerprofilimplementering, ved å bygge et REST API for å håndtere CRUD-operasjoner på et objekt.

Moduler

src mappe opprette en ny app.module.ts fil, og lag deretter en AppModule klasse, som vi eksporterer.

Deretter importerer du AppModule klasse inn main.ts, og løp nest start.

naviger til http://localhost:3000 i nettleseren din og du får en 404-feil:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Dette er fordi vi ennå ikke har definert en rute for basis-URLen til Nest-appen.

Tilbake i app.module.ts, vi har AppModule klasse som vi har er ennå ikke en Nest-modul. For å gjøre det til en Nest-modul legger vi til @Module() dekoratør som er importert fra @nestjs/commonså passerer vi en tom gjenstand.



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

export class AppModule {}

Nå har vi en Nest.js-modul!

OBS: En modul er en klasse som er merket med en @Module() dekoratør.

Hver Nest-applikasjon har en rotmodul, som fungerer som et inngangspunkt for å løse en Nest-applikasjons struktur og relasjoner.

Det anbefales sterkt å bruke flere moduler for å organisere applikasjonens komponenter.

De @Module() decorator gjør det mulig å la utviklere definere metadata om en klasse i Nest-appen.

I tilfellet der det er flere moduler, for eksempel en brukermodul, ordremodul, chattemodul osv app.module.ts skal brukes til å registrere alle andre moduler i Nest-appen.

Opprette ruter; Kontrollere

Kontrollere er nødvendig for å lage ruter i Nest-applikasjoner. En kontrollers formål er å motta spesifikke forespørsler om en Nest-applikasjon; kontrollere forespørsels- og svarsyklusen for ulike ruter i applikasjonen.

Når en HTTP-forespørsel sendes fra klienten til Nest-applikasjonen, håndterer ruten som samsvarer med ruten der forespørselen blir gjort forespørselen og returnerer det riktige svaret.

For å lage en kontroller i en Nest-app, må vi benytte oss av @Controller() dekoratør.

src katalog, opprett en ny fil app.contoller.ts, og der kan vi definere en Nest-kontroller:

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

@Controller({})

export class AppController {}

Det er det! Vi har en veldig fin kontroller, men for å lage en ny rute, må vi først gi Nest-appen vår beskjed om den opprettede kontrolleren.

For å oppnå dette sørger vi for å importere AppController i app.module.ts, og definere informasjon om kontrollerene i @Module() decorator – som en rekke kontrollere:



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

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

export class AppModule {}

Håndtering av GET-forespørsler

Så definerer vi en enkel getUser() rute (med @Get() dekorator som brukes til å håndtere HTTP GET-forespørsler til en spesifisert sti) for å tjene som basisruten, kan vi få tilgang til den samme i nettleseren på https://localhost:3000:



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

@Controller({})

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

Dette resulterer i:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Hmm, her returnerer vi bare en streng, men hva om vi ønsket å returnere et objekt? I stedet for en streng kan vi definere et objekt:



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

@Controller({})

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

naviger til http://localhost:3000 i nettleseren din og du vil se objektet:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Bort fra grunnruten, hva med å lage en rute som ligner på http://localhost:3000/user for å hente alle brukere?

Vi kan lage en kontroller for å håndtere en slik rute på et par måter.

En måte ville være å definere en ny metode ved å bruke @Get() dekoratør/behandler.

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

@Controller({})

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

Nest.js tilbyr dekoratører eller behandlere for alle de forskjellige HTTP-metodene, inkludert @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options()og @Head().

De @All() decorator definerer et endepunkt som håndterer alle de ulike metodene.

Håndtering av POST-forespørsler

Vi kan også definere POST-forespørsler for lagring av data i databasen ved å bruke @Post() dekoratør:

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

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

Deretter tester vi POST-forespørselen med Postman og legger merke til at strengen returneres som definert.

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Du kan spørre, hva om jeg også ønsker å gjøre mer enn å returnere data? Kanskje for å sende data.

For det må du injisere dataene i rutemetoden, som vist:

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

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

Nå, når vi tester POST-forespørselen med Postman, kan vi se dataene som sendes. I dette tilfellet er det bare et tomt objekt:

Sjekk ut vår praktiske, praktiske guide for å lære Git, med beste praksis, bransjeaksepterte standarder og inkludert jukseark. Slutt å google Git-kommandoer og faktisk lære den!

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Dynamisk ruting med ruteparametre

Anta at du vil godta dynamiske data som en del av en forespørsel. Først må vi definere tokenet i banen til ruten, for å merke den dynamiske posisjonen på ruten/URL, og deretter bruke @Param() dekorator, kan ruteparameteren nås slik:

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

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

De userId returneres vellykket:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Håndtering av asynkrone forespørsler

Nest.js er i stand til å håndtere asynkrone forespørsler som returnerer et løfte ved å bruke ulike tilnærminger:

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

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

I tilnærmingen ovenfor håndteres asynkronisitet ved å bruke async nøkkelord. En annen tilnærming er å returnere RxJS observerbare strømmer:

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

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

Her vil Nest.js abonnere på kilden under panseret, og når strømmen er fullført, tar den den siste utsendte verdien automatisk.

Håndtere omdirigeringer i Nest

De @Redirect() decorator brukes til å omdirigere et svar til en annen URL. De @Redirect() decorator godtar to argumenter – URL-en som skal omdirigeres til og statuskoden ved omdirigering, som begge er valgfrie:

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

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

Returnerer statuskode

For å returnere statuskoden for enhver forespørsel som håndteres på Nest.js-serveren, @HttpCode(…) kommer lett gjennom.

I Nest er standardstatuskoden for GET-forespørsler 200, en POST-forespørsel er 201, en feilforespørsel er 304

Statuskoden for en serverforespørsel kan defineres som vist nedenfor:

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.';
  }
}

Håndtering av SLETTE-forespørsler

I likhet med å lage en POST-forespørsel, kan en sletteforespørsel håndteres slik:

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

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

Håndtering av oppdateringsforespørsler

En forespørsel om å oppdatere spesifikke data på serveren kan håndteres ved å bruke @Patch() dekoratør:

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

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

Nå som vi har sett forskjellige måter å definere typiske kontrollere som vi ofte vil ha på en robust server, er det viktig å merke seg at kontrolleren bør være mager, ren og definert per brukstilfelle, slik at hvis det er en annen kontroller for å definere user ruter, bør det opprettes en egen katalog og dedikeres for å håndtere det samme - borte fra AppController.

Så inn user.controller.ts, kan vi konfigurere alle rutebehandlere til å bli prefiks med /user/ ved å skrive kode som vist nedenfor:



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

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

Registrer deg deretter UserController i kontrollerenes arrays i 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 {}

Når vi navigerer til https:localhost:3000/user, returnerer den vellykket:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

For å holde prosjektmappen enda penere enn den er akkurat nå, kan vi definere en user.module.ts fil der vi skal definere UserController:

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

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

export class UserModule {}

Deretter importerer du UserModule inn 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 {}

Med dette vil vi kunne ha samme effekt som tidligere.

OBS: Nest gjør det enkelt å (g)generere (mo)duler og (co)ntrollere ved hjelp av nest g mo og nest g co kommandoer. Spesifikke moduler, for eksempel user modul og kontrollere kan også opprettes raskt ved hjelp av Nest CLI, ved å kjøre kommandoene: nest g mo user – for å lage en brukermodul, og nest g co user – for å opprette en brukerkontroller.

tilbydere

All henting av data fra en database bør håndteres av tilbydere i stedet for kontroller, for å skape et lag med abstraksjon mellom den brukervendte koden og koden som samhandler med potensielt sensitive data. Mellom disse lagene – validering kan settes opp for å sikre riktig databasehåndtering. Med Nest CLI kan vi opprette leverandører ved å generere tjenester:

$ nest g s user

Dette skaper en UserService der vi ville definere all forretningslogikk for UserController, Slik at UserController håndterer kun forespørsler og svar. I user.service.ts, ser vi at @Injectable() dekorator brukes til å definere klassen. I Nest er bruken av @Injectable() decorator er å forvandle tjenester, depoter eller hjelpeklasse til en leverandør.

Leverandører blir injisert i en klasse gjennom konstruktøren. La oss se nærmere på et eksempel.

Tidligere, i user.controller.ts, vi hadde definert forretningslogikken for å hente brukerobjektet, men nå bør vi definere det samme i UserService:



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

@Controller({})

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

Neste, i user.controller.ts fil, la oss definere en konstruktør i UserController klasse. I denne konstruktøren gir vi en privat userService, som er en type av UserService klasse. Det er med denne private vi kan benytte oss av forretningslogikken vi hadde definert tidligere for å hente brukerne:



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();
  }
}

Således, jo UserController klasse, avhenger nå av UserService klasse i et konsept kjent som
avhengighetsinjeksjon.

På samme måte, logikken i begge user.controller.ts og user.service.ts filene oppdateres tilsvarende:



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;
  }
}

La oss nå verifisere at endepunktene fungerer som de burde, ved å bruke Postman.

Demystifying Dependency Injection i Nest.js

Når du bygger mindre komponenter i en applikasjon, for eksempel en klasse eller modul, kan klassen din avhenge av funksjonaliteten til en annen klasse eller modul, for eksempel behovet for å benytte seg av en HTTP-tjeneste levert av en annen klasse for å foreta API-anrop, eller tjenestelag som samhandler med utholdenhetslaget.

Avhengigheter kan gis innen kontroller gjennom avhengighetsinjeksjon.

Dependency injection er et programmeringskonsept og -mønster som uttrykker hvordan deler av en applikasjon leveres til andre deler av applikasjonen som krever det, på en slik måte at det gir høy kohesjon, men løs kobling.

Nest støtter avhengighetsinjeksjon, og du kan bruke den i Nest-applikasjonene dine for å forbedre modulariteten til prosjektet ditt.

En praktisk illustrasjon er avbildet slik:

Anta at klasse A bruker en eller annen funksjonalitet av klasse B. Da sies det at klasse A er avhengig av klasse B. For å bruke klasse B i klasse A må vi derfor lage en forekomst av klasse B først (det vil si å lage en Klasse B objekt): const b = new B ().
Å overføre oppgaven med å lage en forekomst av en klasse til en annen klasse og direkte bruke avhengigheten i klassen som er gitt (injektorkomponenten) er kjent som avhengighetsinjeksjon.

Råd: Dependency injection, eller DI, er et av de grunnleggende konseptene i rammeverk som Spring Boot, Nest.js og Angular.js, hvis du vil lese mer om det, kan du sjekke offisiell Angular-dokumentasjon.

Vanligvis bør en klasse utelukkende konsentrere seg om å oppfylle sine funksjoner i stedet for å bli brukt til å lage forskjellige objekter som den kan kreve eller ikke.

Fordeler med avhengighetsinjeksjon.

  1. Det hjelper med enhetstesting.
  2. Med avhengighetsinjeksjon reduseres kjelekoden, siden initialiseringen av avhengigheter gjøres av injektorkomponenten.
  3. Prosessen med å utvide en søknad blir enklere.
  4. Avhengighetsinjeksjon bidrar til å muliggjøre løs kobling.

Utforsker forespørselsnyttelast

Husk at på forskjellige forespørselsbehandlere som POST og PATCH, kunne vi benytte oss av forespørselen som sendes av serveren ved å bruke @Req() dekoratør. Det er imidlertid mer til det.

I stedet for å hente hele forespørselsobjektet, kan vi bare trykke på spesifikke deler av forespørselsobjektet som vi trenger.
Dermed tilbyr Nest ulike dekoratører som kan brukes med HTTP-rutebehandlere for å få tilgang til Express of Fastify-objekter:

Reddekoratører Fastify eller Express-objekt som er tilgjengelig
`@Request(), @Req()` `req`
`@Response(), @Res()` `re`s`
`@Next()` `neste`
`@Session()` `req.session`
`@Param(param?: streng)` `req.params` / `req.params[param]`
`@Body(param?: streng)` `req.body` / `req.body[param]`
`@Query(param?: streng)` `req.query` / `req.query[param]`
`@Headers(param?: streng)` `req.headers` / `req.headers[param]`
`@Ip()` `req.ip`
`@HostParam()` `req.hosts`

Et typisk eksempel vil være å erstatte @Req() dekoratør som vi brukte tidligere for å få tilgang til hoveddelen av resultatet, med @Body() som allerede kan gi oss direkte tilgang til hoveddelen av en forespørsel uten å bore:



@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 };
}

I noen tilfeller vil du kanskje bare hente spesifikke egenskaper for en forespørselsnyttelast. I så fall må du definere et DTO-skjema (Data Transfer Object). Dataoverføringsskjemaet er et objekt som definerer en kopi av objektet som hentes, men brukes primært til å overføre dataene mellom objektet som skal lagres eller hentes, og utholdenhetslaget. Vanligvis, siden denne prosessen er mer sårbar for angrep – inneholder ikke DTO så mange sensitive datapunkter. Denne egenskapen lar deg også bare hente visse felt av et objekt.

I Nest anbefales det å bruke klasser for å definere et dataoverføringsobjekt, siden verdien til klassene blir bevart under kompilering.

Anta at hoveddelen av forespørselen hadde et token, og du ikke ønsker å hente eller oppdatere slike data, kan en DTO defineres som vist nedenfor:



@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 };
}

Du vil imidlertid legge merke til at vi har definert typen for updateUserDto to ganger; i user.service.ts og i user.controller.ts, men vi må holde kodene våre DRY (Don't Repeat Yourself) slik at vi ikke gjentar oss selv rundt kodebasen.

For dette, i en ny mappe /user/dto i /user katalogen, må vi lage en fil /update-user.dto.ts med .dto.ts utvidelse hvor vi definerer og eksporterer UpdateUserDto klasse for bruk i user.service.ts og user.controller.ts filer:



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 og validering

Anta at det er behov for å validere dataene som mottas når en forespørsel har blitt sendt over serveren.

I Nest kan vi teste riktigheten av alle data som kommer inn eller ut av applikasjonen ved å bruke pipes som installerer to avhengigheter – class-validator og class-transformer.

Et rør er en klasse som er definert med @Injectable() dekoratør (dermed er rør leverandører), som implementerer PipeTransform grensesnitt. De transformerer data til ønsket format og evaluerer data slik at hvis dataene blir funnet gyldige, passerer de uendret, ellers blir det kastet et unntak. For å bruke en pipe, må du binde en forekomst av den bestemte pipe-klassen til den aktuelle konteksten.

De class-validator pakken gjør det mulig å validere dekoratører og ikke-dekoratører, ved hjelp av validator.js internt. Mens class-transformer pakken gjør det mulig å transformere objekter til forekomster av en klasse, transformere klasse til objekt, og serialisere eller deserialisere objekter basert på visse kriterier.

De åtte rørene levert av Nest er:

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

For å demonstrere validering i Nest i denne veiledningen, bruker vi den innebygde ValidationPipe som gjør det mulig å håndheve validering på forespørselsnyttelast og kombineres godt med class-validator pakke; spesifikke regler er deklarert med enkle merknader i Data Transfer Object/lokal klassedeklarasjoner i hver modul.

For å begynne å bruke den innebygde ValidationPipe som eksporteres fra @nestjs/common, la oss installere class-validator og class-transformer pakker:

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

Deretter navigerer du til main.ts hvor vi skal binde ValidationPipe på rotnivået til applikasjonen for å sikre at alle endepunkter i appen vår er beskyttet mot å hente ugyldige data:



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();

Deretter legger vi til noen få valideringsregler i dataoverføringsobjektdeklarasjonene for hver modul ved å deklarere de riktige datasjekkene for hver enkelt data. I vårt tilfelle vil vi erklære passende valideringsregler for name og email in UpdateUserDto:



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

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

  @IsEmail()
  email: string;
}

De @IsString() dekorator sjekker om en gitt data er en ekte streng, og @IsEmail() validator sjekker om en gitt data er en e-post, ellers returnerer den falsk og kaster et unntak.

Nå, hvis vi prøver å lage en PATCH forespørsel til en brukerprofil, og skriv inn et nummer i stedet for en gyldig e-post, for eksempel vil et unntak bli kastet:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Med disse har vi en veldig fin validering i Nest-appen vår.

Mens du validerer med ValidationPipe, er det også mulig å filtrere egenskapene våre som vi ikke vil at metodebehandleren vår skal motta. For eksempel hvis vår behandler bare forventer name og email eiendommer, men en forespørsel omfatter også en country eiendom, kan vi fjerne country egenskap fra det resulterende objektet ved innstilling whitelist til true når vi instansierer 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();

Binding av rør på metodeparameternivå

Rør kan også defineres på params, også. For dette vil vi binde røret på metodens param-nivå.

Før nå, selv om vi definerte userId for å være et tall, vil du legge merke til at hvis vi gjør en forespørsel med userId som en streng, viser det seg vellykket uansett:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

For å sikre at verdien av userId må alltid være et tall, vil vi erklære det bindende getUser() metodebehandler med en valideringssjekk som sikrer det samme:


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

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


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

De ParseIntPipe definerer den innebygde ParseInt Pipe og sikrer at dataene den kjøres mot må være et heltall.

Nå, når vi lager en GET forespørsel til en ugyldig userId av streng "ab", mislykkes valideringen og et unntak blir kastet med en 400 statuskode:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Men med en numerisk verdi passerer valideringen vellykket:

Veiledning til Nest.js – Bygg et REST API med Nest og Node PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.

Vi kan også oppdatere andre metodebehandlere tilsvarende for å sikre riktig validering:



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 };
  }
}

Nå har vi sikret den beste praksis-teknikken for å validere data som kommer inn i applikasjonen vår, kanskje fra en ekstern kilde, når som helst.

konklusjonen

I denne veiledningen har du vært i stand til å lære om det siste barnet på Node.js-blokken; Nest.js, og alt som kreves for å hjelpe deg i gang hvis du ønsker å bygge en applikasjon med den. Du har lært hva Nest er, dets funksjoner, hvordan du oppretter et Nest-prosjekt, hvordan du håndterer innkommende data i en Nest-app og hvordan du validerer innkommende data. Alt i alt har du lært om byggeklossene til alle Nest-applikasjoner, og verdien som hver komponent tilfører en Nest.js-applikasjon.

Fra dette tidspunktet er det fortsatt mye å lære når det gjelder å bygge en bedriftsapplikasjon med Nest, men du har klart å dekke grunnleggende konsepter som kan få deg i gang med alt som ligger foran deg.

Se opp for en ny guide i fremtiden, der vi lærer hvordan du bygger et avslappende API med Nest og MySQL.

Takk for lesing!

Tilleggsressurser

Nest.js Docs
Angular Docs

Tidstempel:

Mer fra Stackabuse