Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Οδηγός για το Nest.js – Δημιουργία REST API με Nest και Node

Ως προγραμματιστής υποστήριξης Node.js, θα συμφωνήσετε ότι από προεπιλογή, το Node.js είναι πολύ γυμνό και δεν κάνει υποθέσεις σχετικά με το τι χρειάζεστε κατά τη δημιουργία μιας εφαρμογής. Ως αποτέλεσμα, είστε υπεύθυνοι για τη ρύθμιση όλων όσων θέλετε να χρησιμοποιήσετε σε μια εφαρμογή, συμπεριλαμβανομένου του χειρισμού της δρομολόγησης, της πραγματοποίησης κλήσεων API, της ρύθμισης TypeScript ή υποδοχών Web ή ακόμα και θεμελιωδών πραγμάτων όπως η οργάνωση κώδικα, η δομή αρχείων και οι συμβάσεις ονομασίας .

Η διαχείριση μιας εφαρμογής μεγάλης κλίμακας μπορεί να είναι μια δύσκολη εργασία, ειδικά εάν δεν έχει σχεδιαστεί με σαφή δομή και αυστηρές οδηγίες οργάνωσης κώδικα.

Το Nest.js προσπαθεί να αντιμετωπίσει ορισμένα από αυτά τα προβλήματα δημιουργώντας μια αφαίρεση γύρω από το Node.js, έτσι ώστε εσείς ως προγραμματιστής να μπορείτε να εστιάσετε στο πρόβλημα της εφαρμογής και όχι σε άλλες μικροσκοπικές λεπτομέρειες υλοποίησης.

Σε αυτόν τον οδηγό, θα μάθετε τις βασικές αρχές του Nest.js από πάνω προς τα κάτω, με στόχο να σας ενημερώσουν ώστε να μπορείτε να δημιουργήσετε εφαρμογές Node.js εταιρικής ποιότητας με τη βοήθεια του Nest.js σε ελάχιστο χρόνο.

Όλα όσα θα μάθουμε μέσω αυτού του οδηγού θα είναι σταδιακά. καλύπτοντας πολύ έδαφος σε εισαγωγικές έννοιες. Για να αξιοποιήσετε στο έπακρο αυτόν τον οδηγό, σας βοηθά να προγραμματίσετε μαζί.

Ας βουτήξουμε αμέσως, παιδιά!

Πηγαίος κώδικας: Ως συνήθως, μπορείτε να διαχωρίσετε και να επεξεργαστείτε τον πηγαίο κώδικα που φιλοξενείται GitHub.

Σημείωση: Θα χρησιμοποιήσουμε το Postman για να δοκιμάσουμε το API στο demo μας. Μπορείτε να το κατεβάσετε στο Σελίδα λήψης ταχυδρόμων. Εναλλακτικά, μπορείτε απλά να χρησιμοποιήσετε το πρόγραμμα περιήγησης, τη γραμμή εντολών curl εργαλείο ή οποιοδήποτε άλλο εργαλείο που ίσως γνωρίζετε.

Τι είναι το Nest.js

Σκεφτείτε το Nest.js ως ένα υπερσύνολο του Node.js που αφαιρεί δύσκολες εργασίες, εργαλεία και κώδικα boilerplate, ενώ προσθέτει επίσης ένα πλήρες κιτ εργαλείων για την ανάπτυξη της εφαρμογής σας χρησιμοποιώντας σύγχρονα JavaScript και TypeScript.

Το Nest.js παρέχει μια εξαρχής αρχιτεκτονική εφαρμογών που επιτρέπει στους προγραμματιστές και τις ομάδες να δημιουργούν εξαιρετικά επεκτάσιμες, ελεγχόμενες, χαλαρά συνδεδεμένες και εύκολα συντηρήσιμες, αξιοποιώντας άμεσα διαθέσιμες και εξέχουσες επιλογές και ενότητες στην κοινότητα, όπως αυτές που είναι διαθέσιμες στο Εφαρμογές Express.js. Θα μπορούσατε ακόμη και να ανταλλάξετε το Express (το οποίο χρησιμοποιεί κάτω από την κουκούλα από προεπιλογή) με το Fastify, αλλά κάτι τέτοιο θα σήμαινε ότι ίσως χρειαστεί να χρησιμοποιήσετε διαφορετικές βιβλιοθήκες συμβατές με το Fastify στην εφαρμογή σας.

Συνδυάζει τα χαρακτηριστικά του Λειτουργικού Προγραμματισμού, του Αντικειμενοστρεφούς Προγραμματισμού και του Λειτουργικού Αντιδραστικού Προγραμματισμού και με περισσότερα από 52.4k αστέρια και 6.2k πιρούνια σε GitHub και εβδομαδιαίο πλήθος λήψεων έως και 1,784,004, το προοδευτικό πλαίσιο Node.js είναι ένα δημοφιλές εργαλείο για τη δημιουργία αποτελεσματικών, επεκτάσιμων και εταιρικού επιπέδου εφαρμογών διακομιστή.

Χαρακτηριστικά του Nest.js

Οι ακόλουθοι είναι οι λόγοι για τους οποίους το Nest.js έχει γίνει ένα τόσο δημοφιλές πλαίσιο Node.js:

  1. Το Nest.js δημιουργήθηκε για να βοηθήσει τους προγραμματιστές να δημιουργήσουν και μονολιθικές εφαρμογές και μικροϋπηρεσίες.
  2. Αν και είναι ισχυρό, είναι επίσης φιλικό προς τους προγραμματιστές να συνεργαστείτε. εύκολο στη χρήση, γρήγορο στην εκμάθηση και εύκολο στην εφαρμογή.
  3. Αξιοποιεί το TypeScript (ένα υπερσύνολο JavaScript) από το κουτί και δίνει χώρο στους προγραμματιστές να γράφουν κώδικα που να μπορεί να διατηρηθεί χωρίς σφάλματα χρόνου εκτέλεσης.
  4. Διαθέτει διεπαφή γραμμής εντολών που βοηθά στην ενίσχυση της παραγωγικότητας των προγραμματιστών και στην ευκολία ανάπτυξης.
  5. Κατά τη δημιουργία με το Nest.js, οι διαδικασίες ανάπτυξης βελτιώνονται και εξοικονομείται χρόνος είτε κάνετε bootstrapping ένα ελάχιστο βιώσιμο προϊόν είτε εργάζεστε σε μια εφαρμογή, επειδή το Nest διαθέτει μια εκπληκτική δομή φακέλου έργου από προεπιλογή.
  6. Υποστηρίζει μια ποικιλία λειτουργικών μονάδων ειδικά για τη Nest που βοηθούν στην ενσωμάτωση κοινών εννοιών και τεχνολογιών, όπως TypeORM, GraphQL, καταγραφή, επικύρωση, Mongoose, WebSockets, προσωρινή αποθήκευση κ.λπ.
  7. Το Nest.js μπορεί να υπερηφανεύεται ότι διαθέτει μερικά από τα καλύτερα έγγραφα για οποιοδήποτε πλαίσιο εκεί έξω. Η τεκμηρίωσή του είναι εμπεριστατωμένη, κατανοητή και χρήσιμη για την εξοικονόμηση χρόνου εντοπισμού σφαλμάτων, καθώς ολοκληρώνεται αβίαστα όταν υπάρχει ανάγκη για λύση σε ένα πρόβλημα.
  8. Το Nest.js ενσωματώνεται με το Jest, γεγονός που καθιστά εύκολη τη σύνταξη δοκιμών μονάδας στις εφαρμογές σας.
  9. Είναι κατασκευασμένο τόσο για μικρές όσο και για μεγάλης κλίμακας εταιρικές εφαρμογές.

Δημιουργία έργου Nest.js

Για να ξεκινήσετε με το Nest.js στον τοπικό σας υπολογιστή, πρέπει πρώτα να εγκαταστήσετε τη διεπαφή γραμμής εντολών Nest (CLI), η οποία θα βοηθήσει στη δημιουργία ενός νέου φακέλου έργου Nest.js και στη συμπλήρωση του φακέλου με βασικά αρχεία και λειτουργικές μονάδες που απαιτούνται για Εφαρμογή Nest.js.

Εκτελέστε την ακόλουθη εντολή για να εγκαταστήσετε τη διεπαφή γραμμής εντολών Nest.js:

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

Αφού εγκαταστήσετε με επιτυχία το Nest.js CLI παγκοσμίως στον τοπικό σας υπολογιστή, μπορείτε να το εκτελέσετε nest στη γραμμή εντολών για να δούμε διάφορες εντολές στις οποίες μπορούμε να πατήσουμε:

$ nest

Αποτελέσματα σε:

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

Εδώ, σας παρουσιάζεται πώς να κάνετε χρήση των εντολών και μπορείτε τώρα να πατήσετε το new|n [options] [name] εντολή για τη δημιουργία του πρώτου σας έργου Nest.js:

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

Στη συνέχεια, θα ερωτηθείτε ποιος διαχειριστής πακέτων θα θέλατε να χρησιμοποιήσετε:

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

Μη διστάσετε να επιλέξετε τον διαχειριστή πακέτων της επιλογής σας, θα πάω μαζί pnpm. Αυτό οφείλεται στο γεγονός ότι είναι περίπου τρεις φορές πιο αποτελεσματικό και ταχύτερο από το NPM και με ένα γρήγορο σύστημα προσωρινής μνήμης, το PNPM είναι επίσης ταχύτερο από το Yarn.

Αφού επιλέξετε έναν διαχειριστή πακέτων, η διαδικασία εγκατάστασης συνεχίζεται και, στη συνέχεια, θα δημιουργηθεί η εφαρμογή Nest.js.

Τώρα μπορείς cd στο έργο που δημιουργήθηκε πρόσφατα και ανοίξτε το με έναν επεξεργαστή της επιλογής σας:

$ cd getting-started-with-nestjs

Με το έργο που δημιουργήθηκε τώρα, μπορούμε να το εκτελέσουμε με μία από τις ακόλουθες εντολές:

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

Εάν ρίξετε μια ματιά στο package.json αρχείο, θα παρατηρήσετε στο τμήμα του σεναρίου, την τιμή για pnpm run start is nest start:


    
"start": "nest start",

Αυτό σημαίνει ότι μπορείτε επίσης να εκτελέσετε την εφαρμογή Nest.js εκτελώντας:

$ nest start

Μια ματιά στη δομή του έργου Nest.js

Ας ρίξουμε μια προσεκτική ματιά στο πώς είναι δομημένη μια εφαρμογή Nest:

/package.json

Η package.json Το αρχείο είναι η καρδιά του Node.js και κατά επέκταση, το έργο Nest.js. Διατηρεί όλα τα μεταδεδομένα σχετικά με το έργο και ορίζει διάφορες λειτουργικές ιδιότητες του έργου που απαιτούνται για την εγκατάσταση εξαρτήσεων εφαρμογών ή την εκτέλεση σεναρίων έργου.

Έχουμε ήδη δει την ικανότητα του start γραφή.

Η start:dev Το προφίλ καθιστά δυνατή την παρακολούθηση αλλαγών στην εφαρμογή και τη φόρτωσή της αυτόματα, χωρίς να χρειάζεται να διακόψετε την εφαρμογή και να την επανεκκινήσετε – και προορίζεται για ανάπτυξη. ο start:prod Το σενάριο είναι χρήσιμο όταν θέλετε να ελέγξετε εάν η εφαρμογή σας είναι έτοιμη για παραγωγή, καθώς και όταν την αναπτύσσετε στην παραγωγή, μαζί με άλλα σενάρια για τη δοκιμή της εφαρμογής Nest.js.

@nestjs/platform-express ορίζει το express ως τον προεπιλεγμένο διακομιστή HTTP σε μια εφαρμογή Nest.

/tsconfig.json

Η tsconfig.json Το αρχείο είναι ένα αρχείο γραμμένο σε JSON (JavaScript Object Notation) που ορίζει τις επιλογές που σχετίζονται με το TypeScript που απαιτούνται για τη μεταγλώττιση της εφαρμογής Nest.

/nest-cli.json

Αυτό περιέχει μεταδεδομένα που απαιτούνται για τη δημιουργία, την οργάνωση ή την ανάπτυξη εφαρμογών Nest.

/test

Αυτός ο κατάλογος περιέχει όλα τα αρχεία που απαιτούνται για την εκτέλεση δοκιμών Nest. Το Nest χρησιμοποιεί το πλαίσιο Jest για δοκιμές με διαμόρφωση Jest στο jest-e2e.json αρχείο.

/src

Η src κατάλογος είναι ο γονικός φάκελος για τον πυρήνα του έργου Nest. Κρατάει το main.ts αρχείο που είναι το αρχείο όπου ξεκινά η εφαρμογή Nest. Η δουλειά του main.ts το αρχείο πρόκειται να φορτωθεί AppModule που εισάγεται από /src/app.module.ts.

Αργότερα σε αυτόν τον οδηγό, θα μάθουμε για τις Ενότητες. ένα από τα κύρια στοιχεία μιας εφαρμογής Nest.js.

Η AppModule είναι μια κλάση που δημιουργείται ως λειτουργική μονάδα, χρησιμοποιώντας το @Module διακοσμητής. Στο app.module.ts αρχείου, AppService από ./app.service και AppController από ./app.controller εισάγονται επίσης.

Η AppController είναι επίσης μια κλάση που δημιουργείται χρησιμοποιώντας το @Controller διακοσμητής, ενώ η AppService είναι μια κλάση που δημιουργείται χρησιμοποιώντας το @Injectable σχόλιο.

Το ωραίο με το Nest είναι ότι έχει πολύ λίγους διακοσμητές που προσθέτουν μεταδεδομένα σε οποιαδήποτε τάξη και αυτά τα μεταδεδομένα καθορίζουν τον σκοπό αυτής της κλάσης, έτσι ώστε:

  • @Controller()μετατρέπει μια κλάση σε ελεγκτή.
  • @Module() μετατρέπει μια τάξη σε μια ενότητα.
  • @Injectable() μετατρέπει μια τάξη σε πάροχο.

Επίσης στο src κατάλογος είναι ο app.controller.spec.ts αρχείο, το οποίο είναι ένα δοκιμαστικό αρχείο για Ελεγκτές.

Μπορούμε να εκτελέσουμε την εφαρμογή χρησιμοποιώντας nest start.

Η εφαρμογή ξεκινά στις http://localhost:3000 στο πρόγραμμα περιήγησής σας:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Μπορούμε να αλλάξουμε το περιεχόμενο που εμφανίζεται στο http://localhost:3000, κατευθυνόμενοι προς το app.service.ts αρχείο, όπου ορίστηκε ο πάροχος για τη διαδρομή ευρετηρίου.

Τα δομικά στοιχεία μιας εφαρμογής Nest.js

Υπάρχουν τρία κύρια στοιχεία μιας εφαρμογής Nest.js:

  1. ενότητες
  2. ελεγκτές
  3. Προμηθευτές

Για να μάθετε για τα δομικά στοιχεία μιας εφαρμογής Nest, ας καθαρίσουμε πρώτα το έργο Nest, διαγράφοντας το app.controller.spec.ts, ./app.service, app.module.ts, να ./app.controller αρχεία? αφήνοντας απλώς main.ts, για μίμηση ενός κύκλου ζωής ανάπτυξης από την αρχή.

Σε αυτό το σημείο, όταν αφαιρούμε τα εισαγόμενα AppModule αρχείο από main.ts, μας ζητείται ότι δεν παρασχέθηκε όρισμα για «μονάδα».

Για να δείξουμε τα δομικά στοιχεία μιας εφαρμογής Nest, θα ρίξουμε μια ματιά σε μια απλή υλοποίηση του προφίλ χρήστη, δημιουργώντας ένα REST API για το χειρισμό λειτουργιών CRUD σε ένα αντικείμενο.

ενότητες

Στο src φάκελο δημιουργήστε ένα νέο app.module.ts αρχείο και, στη συνέχεια, δημιουργήστε ένα AppModule κατηγορίας, την οποία εξάγουμε.

Στη συνέχεια, εισαγάγετε το AppModule τάξη σε main.ts, και τρέξτε nest start.

Πλοηγηθείτε στο http://localhost:3000 στο πρόγραμμα περιήγησής σας και θα λάβετε ένα σφάλμα 404:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Αυτό συμβαίνει επειδή δεν έχουμε ακόμη ορίσει μια διαδρομή για τη βασική διεύθυνση URL της εφαρμογής Nest.

Επιστροφή σε app.module.ts, έχουμε το AppModule Η κλάση που έχουμε δεν είναι ακόμη λειτουργική μονάδα Nest. Για να το κάνουμε λειτουργική μονάδα Nest, προσθέτουμε το @Module() διακοσμητής που εισάγεται από @nestjs/commonτότε περνάμε ένα κενό αντικείμενο.



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

export class AppModule {}

Τώρα, έχουμε μια λειτουργική μονάδα Nest.js!

Σημείωση: Μια ενότητα είναι μια τάξη που σχολιάζεται με α @Module() διακοσμητής.

Κάθε εφαρμογή Nest έχει μια λειτουργική μονάδα root, η οποία χρησιμεύει ως σημείο εισόδου για την επίλυση της δομής και των σχέσεων μιας εφαρμογής Nest.

Συνιστάται ιδιαίτερα η χρήση πολλαπλών λειτουργικών μονάδων για την οργάνωση των στοιχείων της εφαρμογής σας.

Η @Module() Το decorator δίνει τη δυνατότητα στους προγραμματιστές να ορίζουν μεταδεδομένα για μια τάξη στην εφαρμογή Nest.

Σε περίπτωση που υπάρχουν πολλές ενότητες, όπως μια ενότητα χρηστών, μια ενότητα παραγγελιών, μια ενότητα συνομιλίας κ.λπ., η app.module.ts θα πρέπει να χρησιμοποιείται για την εγγραφή όλων των άλλων λειτουργικών μονάδων της εφαρμογής Nest.

Δημιουργία Διαδρομών. Ελεγκτές

Απαιτούνται ελεγκτές για τη δημιουργία διαδρομών στις εφαρμογές Nest. Ο σκοπός ενός ελεγκτή είναι να λαμβάνει συγκεκριμένα αιτήματα για μια εφαρμογή Nest. έλεγχος του κύκλου αιτήματος και απόκρισης για διάφορες διαδρομές εντός της εφαρμογής.

Όταν γίνεται ένα αίτημα HTTP από τον πελάτη στην εφαρμογή Nest, η διαδρομή που ταιριάζει με τη διαδρομή στην οποία υποβάλλεται το αίτημα χειρίζεται το αίτημα και επιστρέφει την κατάλληλη απάντηση.

Για να δημιουργήσουμε έναν ελεγκτή σε μια εφαρμογή Nest, πρέπει να χρησιμοποιήσουμε το @Controller() διακοσμητής.

Στο src κατάλογο, δημιουργήστε ένα νέο αρχείο app.contoller.ts, και σε αυτό, μπορούμε να ορίσουμε έναν ελεγκτή Nest:

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

@Controller({})

export class AppController {}

Αυτό είναι! Έχουμε ένα πολύ ωραίο χειριστήριο, αλλά για να δημιουργήσουμε μια νέα διαδρομή, πρέπει πρώτα να ενημερώσουμε την εφαρμογή Nest για το χειριστήριο που δημιουργήθηκε.

Για να το πετύχουμε αυτό φροντίζουμε να εισάγουμε AppController στο app.module.ts και ορίστε πληροφορίες σχετικά με τους ελεγκτές στο @Module() διακοσμητής – ως μια σειρά ελεγκτών:



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

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

export class AppModule {}

Χειρισμός αιτημάτων GET

Στη συνέχεια ορίζουμε ένα απλό getUser() διαδρομή (με το @Get() διακοσμητής που χρησιμοποιείται για το χειρισμό αιτημάτων HTTP GET σε μια καθορισμένη διαδρομή) για να χρησιμεύσει ως η βασική διαδρομή, μπορούμε να έχουμε πρόσβαση στο πρόγραμμα περιήγησης στο https://localhost:3000:



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

@Controller({})

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

Αυτο εχει ως αποτελεσμα:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Χμ, εδώ επιστρέφουμε μόνο μια συμβολοσειρά, αλλά τι γίνεται αν θέλαμε να επιστρέψουμε ένα αντικείμενο; Αντί για συμβολοσειρά, μπορούμε να ορίσουμε ένα αντικείμενο:



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

@Controller({})

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

Πλοηγηθείτε στο http://localhost:3000 στο πρόγραμμα περιήγησής σας και θα δείτε το αντικείμενο:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Μακριά από τη βασική διαδρομή, τι θα λέγατε να δημιουργήσετε μια διαδρομή παρόμοια με http://localhost:3000/user για την ανάκτηση όλων των χρηστών;

Μπορούμε να δημιουργήσουμε έναν ελεγκτή για να χειριστεί μια τέτοια διαδρομή με δύο τρόπους.

Ένας τρόπος θα ήταν να ορίσετε μια νέα μέθοδο, χρησιμοποιώντας το @Get() διακοσμητής/χειριστής.

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

@Controller({})

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

Το Nest.js παρέχει διακοσμητές ή χειριστές για όλες τις διάφορες μεθόδους HTTP, συμπεριλαμβανομένων @Get(), @Post(), @Put(), @Delete(), @Patch(), @Options(), να @Head().

Η @All() Ο διακοσμητής ορίζει ένα τελικό σημείο που χειρίζεται όλες τις διάφορες μεθόδους.

Χειρισμός αιτημάτων POST

Μπορούμε επίσης να ορίσουμε αιτήματα POST για αποθήκευση δεδομένων στη βάση δεδομένων, χρησιμοποιώντας το @Post() διακοσμητής:

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

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

Στη συνέχεια, δοκιμάζουμε το αίτημα POST χρησιμοποιώντας τον Postman και παρατηρούμε ότι η συμβολοσειρά επιστρέφεται με επιτυχία όπως ορίζεται.

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Θα μπορούσατε να ρωτήσετε, τι γίνεται αν θέλω επίσης να κάνω περισσότερα από την επιστροφή δεδομένων; Ίσως, για αποστολή δεδομένων.

Για αυτό, πρέπει να εισάγετε τα δεδομένα μέσα στη μέθοδο διαδρομής, όπως φαίνεται:

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

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

Τώρα, όταν δοκιμάζουμε το αίτημα POST με τον Postman, μπορούμε να δούμε τα δεδομένα που αποστέλλονται. Σε αυτήν την περίπτωση, είναι απλώς ένα κενό αντικείμενο:

Ρίξτε μια ματιά στον πρακτικό μας οδηγό για την εκμάθηση του Git, με βέλτιστες πρακτικές, πρότυπα αποδεκτά από τον κλάδο και συμπεριλαμβανόμενο φύλλο εξαπάτησης. Σταματήστε τις εντολές του Git στο Google και πραγματικά μαθαίνουν το!

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Δυναμική δρομολόγηση με παραμέτρους διαδρομής

Ας υποθέσουμε ότι θέλετε να αποδεχτείτε δυναμικά δεδομένα ως μέρος ενός αιτήματος. Αρχικά, πρέπει να ορίσουμε το διακριτικό στη διαδρομή της διαδρομής, για να σημειώσουμε τη δυναμική θέση στη διαδρομή/URL και στη συνέχεια να χρησιμοποιήσουμε το @Param() διακοσμητής, η παράμετρος διαδρομής μπορεί να προσπελαστεί ως εξής:

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

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

Η userId επιστρέφεται με επιτυχία:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Χειρισμός ασύγχρονων αιτημάτων

Το Nest.js είναι σε θέση να χειρίζεται ασύγχρονα αιτήματα που επιστρέφουν μια υπόσχεση χρησιμοποιώντας διάφορες προσεγγίσεις:

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

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

Στην παραπάνω προσέγγιση, η ασυγχρονικότητα αντιμετωπίζεται χρησιμοποιώντας το async λέξη-κλειδί. Μια άλλη προσέγγιση είναι η επιστροφή των παρατηρήσιμων ροών RxJS:

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

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

Εδώ, το Nest.js θα εγγραφεί στην πηγή κάτω από την κουκούλα και όταν ολοκληρωθεί η ροή, θα λάβει αυτόματα την τελευταία τιμή που εκπέμπεται.

Χειρισμός ανακατευθύνσεων στο Nest

Η @Redirect() Ο διακοσμητής χρησιμοποιείται για να ανακατευθύνει μια απάντηση σε διαφορετική διεύθυνση URL. ο @Redirect() Ο διακοσμητής δέχεται δύο ορίσματα – τη διεύθυνση URL προς ανακατεύθυνση και τον κωδικό κατάστασης κατά την ανακατεύθυνση, και τα δύο είναι προαιρετικά:

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

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

Κωδικός κατάστασης επιστροφής

Για να επιστρέψετε τον κωδικό κατάστασης για οποιοδήποτε αίτημα χειρίζεται στον διακομιστή Nest.js, το @HttpCode(…) περνά εύκολα.

Στο Nest, ο προεπιλεγμένος κωδικός κατάστασης για αιτήματα GET είναι 200, ένα αίτημα POST είναι 201, ένα αίτημα σφάλματος είναι 304

Ο κωδικός κατάστασης για ένα αίτημα διακομιστή μπορεί να οριστεί όπως φαίνεται παρακάτω:

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

Χειρισμός αιτημάτων DELETE

Παρόμοια με την υποβολή αιτήματος POST, ένα αίτημα διαγραφής μπορεί να αντιμετωπιστεί ως εξής:

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

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

Χειρισμός αιτημάτων ΕΝΗΜΕΡΩΣΗΣ

Ένα αίτημα για ενημέρωση συγκεκριμένων δεδομένων στον διακομιστή μπορεί να διεκπεραιωθεί χρησιμοποιώντας το @Patch() διακοσμητής:

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

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

Τώρα που είδαμε διάφορους τρόπους ορισμού τυπικών ελεγκτών που θα είχαμε συχνά σε έναν ισχυρό διακομιστή, είναι σημαντικό να σημειωθεί ότι ο ελεγκτής πρέπει να είναι λιτός, καθαρός και καθορισμένος ανά περίπτωση χρήσης, έτσι ώστε εάν υπάρχει άλλος ελεγκτής για τον καθορισμό user διαδρομές, τότε ένας ξεχωριστός κατάλογος θα πρέπει να δημιουργηθεί και να αφιερωθεί για το χειρισμό των ίδιων – μακριά από το AppController.

Στη συνέχεια στο user.controller.ts, μπορούμε να διαμορφώσουμε όλους τους χειριστές διαδρομών σε αυτό για να έχουν το πρόθεμα /user/ γράφοντας κώδικα όπως φαίνεται παρακάτω:



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

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

Στη συνέχεια, εγγραφείτε UserController στις συστοιχίες ελεγκτών μέσα 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 {}

Όταν πλοηγούμαστε στο https:localhost:3000/user, επιστρέφει με επιτυχία:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Για να διατηρήσουμε τον φάκελο του έργου ακόμα πιο τακτοποιημένο από ό,τι είναι τώρα, μπορούμε να ορίσουμε α user.module.ts αρχείο όπου θα ορίσουμε το UserController:

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

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

export class UserModule {}

Στη συνέχεια, εισαγωγή UserModule σε 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 {}

Με αυτό, θα μπορέσουμε να έχουμε το ίδιο αποτέλεσμα όπως προηγουμένως.

Σημείωση: Το Nest διευκολύνει τη (g)δημιουργία (mo)dules και (co)trollers χρησιμοποιώντας το nest g mo και nest g co εντολές. Συγκεκριμένες ενότητες, όπως το user Η μονάδα και οι ελεγκτές μπορούν επίσης να δημιουργηθούν γρήγορα χρησιμοποιώντας το Nest CLI, εκτελώντας τις εντολές: nest g mo user – για να δημιουργήσετε μια λειτουργική μονάδα χρήστη και nest g co user – για να δημιουργήσετε έναν ελεγκτή χρήστη.

Προμηθευτές

Όλη η ανάκτηση δεδομένων από μια βάση δεδομένων θα πρέπει να γίνεται από παρόχους αντί για ελεγκτές, για να δημιουργηθεί ένα επίπεδο αφαίρεσης μεταξύ του κώδικα που αντιμετωπίζει ο χρήστης και του κώδικα που αλληλεπιδρά με δυνητικά ευαίσθητα δεδομένα. Μεταξύ αυτών των επιπέδων - μπορεί να ρυθμιστεί η επικύρωση για να διασφαλιστεί ο σωστός χειρισμός της βάσης δεδομένων. Με το Nest CLI, μπορούμε να δημιουργήσουμε παρόχους δημιουργώντας υπηρεσίες:

$ nest g s user

Αυτό δημιουργεί ένα UserService όπου θα προσδιορίζαμε όλη την επιχειρηματική λογική για το UserController, Έτσι ώστε να UserController χειρίζεται μόνο αιτήματα και απαντήσεις. Σε user.service.ts, βλέπουμε ότι το @Injectable() Ο διακοσμητής χρησιμοποιείται για τον ορισμό της τάξης. Στο Nest, η χρήση του @Injectable() Ο διακοσμητής είναι να μετατρέψει τις υπηρεσίες, τα αποθετήρια ή την τάξη βοηθών σε πάροχο.

Οι πάροχοι εγχέονται σε μια κλάση μέσω του κατασκευαστή της. Ας ρίξουμε μια προσεκτική ματιά σε ένα παράδειγμα.

Νωρίτερα, στο user.controller.ts, είχαμε ορίσει την επιχειρηματική λογική για τη λήψη του αντικειμένου χρήστη, αλλά τώρα, θα πρέπει να ορίσουμε το ίδιο στο UserService:



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

@Controller({})

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

Στη συνέχεια, στο user.controller.ts αρχείο, ας ορίσουμε έναν κατασκευαστή στο UserController τάξη. Σε αυτόν τον κατασκευαστή, παρέχουμε ένα ιδιωτικό userService, που είναι ένας τύπος του UserService τάξη. Είναι με αυτό το ιδιωτικό που μπορούμε να αξιοποιήσουμε την επιχειρηματική λογική που είχαμε ορίσει νωρίτερα για την ανάκτηση των χρηστών:



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

Έτσι, η UserController τάξη, τώρα εξαρτάται από το UserService τάξη σε μια έννοια γνωστή ως
ένεση εξάρτησης.

Με τον ίδιο τρόπο, η λογική και στα δύο user.controller.ts και user.service.ts τα αρχεία ενημερώνονται αναλόγως:



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

Τώρα, ας επαληθεύσουμε ότι τα τελικά σημεία λειτουργούν όπως θα έπρεπε, χρησιμοποιώντας το Postman.

Demystifying Dependency Injection στο Nest.js

Όταν δημιουργείτε μικρότερα στοιχεία μιας εφαρμογής, όπως μια κλάση ή μια λειτουργική μονάδα, η κλάση σας μπορεί να εξαρτάται από τη λειτουργικότητα μιας άλλης κλάσης ή λειτουργικής μονάδας, για παράδειγμα, την ανάγκη να αξιοποιήσετε μια υπηρεσία HTTP που παρέχεται από διαφορετική κλάση για να πραγματοποιήσετε κλήσεις API ή επίπεδα υπηρεσιών που αλληλεπιδρούν με το επίπεδο επιμονής.

Οι εξαρτήσεις μπορούν να παρέχονται στους ελεγκτές μέσω ένεση εξάρτησης.

Η έγχυση εξάρτησης είναι μια έννοια προγραμματισμού και ένα μοτίβο που εκφράζει τον τρόπο με τον οποίο τμήματα μιας εφαρμογής παραδίδονται σε άλλα μέρη της εφαρμογής που τα απαιτούν, με τέτοιο τρόπο ώστε να παρέχεται υψηλή συνοχή αλλά χαλαρή σύζευξη.

Το Nest υποστηρίζει την ένεση εξάρτησης και μπορείτε να το χρησιμοποιήσετε στις εφαρμογές Nest για να βελτιώσετε τη σπονδυλωτότητα του έργου σας.

Μια πρακτική απεικόνιση απεικονίζεται ως εξής:

Ας υποθέσουμε ότι η κλάση Α χρησιμοποιεί κάποια λειτουργικότητα της κλάσης Β. Τότε λέγεται ότι η κλάση Α εξαρτάται από την κλάση Β. Έτσι, για να χρησιμοποιήσουμε την κλάση Β στην κλάση Α, πρέπει πρώτα να δημιουργήσουμε μια παρουσία της κλάσης Β (δηλαδή, να δημιουργήσουμε μια Αντικείμενο κατηγορίας Β): const b = new B ().
Η μεταφορά της εργασίας δημιουργίας ενός στιγμιότυπου μιας κλάσης σε μια άλλη κλάση και η απευθείας χρήση της εξάρτησης στην κλάση που παρέχεται (το στοιχείο του εγχυτήρα) είναι γνωστή ως ένεση εξάρτησης.

Συμβουλές: Η έγχυση εξάρτησης ή DI, είναι μια από τις θεμελιώδεις έννοιες σε πλαίσια όπως το Spring Boot, το Nest.js και το Angular.js. Εάν θέλετε να διαβάσετε περισσότερα σχετικά με αυτό, μπορείτε να ελέγξετε το επίσημη τεκμηρίωση Angular.

Συνήθως, μια κλάση θα πρέπει να επικεντρώνεται αποκλειστικά στην εκπλήρωση των λειτουργιών της αντί να χρησιμοποιείται για τη δημιουργία διαφόρων αντικειμένων που μπορεί να απαιτήσει ή όχι.

Οφέλη από την ένεση εξάρτησης.

  1. Βοηθά στη δοκιμή μονάδας.
  2. Με την έγχυση εξάρτησης, ο κωδικός λέβητα μειώνεται, αφού η αρχικοποίηση των εξαρτήσεων γίνεται από το εξάρτημα του μπεκ.
  3. Η διαδικασία επέκτασης μιας εφαρμογής γίνεται ευκολότερη.
  4. Η έγχυση εξάρτησης βοηθά στη χαλαρή σύζευξη.

Εξερεύνηση αιτήματος ωφέλιμων φορτίων

Να θυμάστε ότι σε διάφορους χειριστές αιτημάτων όπως POST και PATCH, μπορέσαμε να αξιοποιήσουμε το αίτημα που αποστέλλεται από τον διακομιστή χρησιμοποιώντας το @Req() διακοσμητής. Ωστόσο, υπάρχουν περισσότερα σε αυτό.

Αντί να ανακτήσουμε ολόκληρο το αντικείμενο αίτησης, μπορούμε απλώς να πατήσουμε σε συγκεκριμένα μέρη του αντικειμένου αιτήματος που χρειαζόμαστε.
Έτσι, η Nest παρέχει διάφορους διακοσμητές που μπορούν να χρησιμοποιηθούν με τους χειριστές δρομολογίων HTTP για πρόσβαση σε αντικείμενα Express of Fastify:

Διακοσμητές φωλιών Αντικείμενο Fastify ή Express στο οποίο γίνεται πρόσβαση
`@Request(), @Req()` «απαίτηση».
`@Response(), @Res()` «ρε»ς
`@Next()` «επόμενο».
`@Session()` «αίτηση συνεδρίας».
`@Param(param?: συμβολοσειρά)` `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() διακοσμητής που χρησιμοποιήσαμε προηγουμένως για να αποκτήσουμε πρόσβαση στο σώμα του αποτελέσματος, με το @Body() που μπορεί ήδη να μας δώσει άμεση πρόσβαση στο σώμα ενός αιτήματος χωρίς γεώτρηση:



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

Σε ορισμένες περιπτώσεις, μπορεί να θέλετε να ανακτήσετε μόνο συγκεκριμένες ιδιότητες ενός ωφέλιμου φορτίου αιτήματος. Σε αυτήν την περίπτωση, θα πρέπει να ορίσετε ένα σχήμα αντικειμένου μεταφοράς δεδομένων (DTO). Το σχήμα μεταφοράς δεδομένων είναι ένα αντικείμενο που ορίζει ένα αντίγραφο του αντικειμένου που ανακτάται, αλλά χρησιμοποιείται κυρίως για τη μεταφορά των δεδομένων μεταξύ του αντικειμένου που υποτίθεται ότι θα αποθηκευτεί ή θα ανακτηθεί και του επιπέδου επιμονής. Συνήθως, δεδομένου ότι αυτή η διαδικασία είναι πιο ευάλωτη σε επιθέσεις – το DTO δεν περιέχει τόσα ευαίσθητα σημεία δεδομένων. Αυτό το χαρακτηριστικό σας επιτρέπει επίσης να ανακτήσετε μόνο ορισμένα πεδία ενός αντικειμένου.

Στο Nest, συνιστάται η χρήση κλάσεων για τον ορισμό ενός αντικειμένου μεταφοράς δεδομένων, καθώς η τιμή των κλάσεων διατηρείται κατά τη μεταγλώττιση.

Αν υποθέσουμε ότι το σώμα της αίτησης είχε ένα διακριτικό και δεν θέλετε να ανακτήσετε ή να ενημερώσετε τέτοια δεδομένα, τότε μπορεί να οριστεί ένας DTO όπως φαίνεται παρακάτω:



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

Ωστόσο, θα παρατηρήσετε ότι έχουμε ορίσει τον τύπο για updateUserDto εις διπλούν; σε user.service.ts και user.controller.ts, αλλά πρέπει να διατηρήσουμε τους κωδικούς μας DRY (Don't Repeat Yourself) ώστε να μην επαναλαμβανόμαστε γύρω από τη βάση κωδικών.

Για αυτό, σε νέο φάκελο /user/dto στο /user κατάλογο, πρέπει να δημιουργήσουμε ένα αρχείο /update-user.dto.ts με .dto.ts επέκταση όπου ορίζουμε και εξάγουμε το UpdateUserDto τάξη για χρήση στο user.service.ts και user.controller.ts αρχεία:



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

Σωλήνας και επικύρωση

Ας υποθέσουμε ότι υπάρχει ανάγκη επικύρωσης των δεδομένων που λαμβάνονται όταν έχει γίνει ένα αίτημα μέσω του διακομιστή.

Στο Nest, μπορούμε να ελέγξουμε την ορθότητα τυχόν δεδομένων που εισέρχονται ή εξέρχονται από την εφαρμογή χρησιμοποιώντας σωλήνες που εγκαθιστούν δύο εξαρτήσεις – class-validator και class-transformer.

Ένας σωλήνας είναι μια κλάση που ορίζεται με το @Injectable() διακοσμητής (άρα, οι σωλήνες είναι πάροχοι), που υλοποιεί την PipeTransform διεπαφή. Μετασχηματίζουν τα δεδομένα στην επιθυμητή μορφή και αξιολογούν τα δεδομένα έτσι ώστε εάν τα δεδομένα κριθούν έγκυρα, περνούν αμετάβλητα, διαφορετικά δημιουργείται εξαίρεση. Για να χρησιμοποιήσετε έναν σωλήνα, πρέπει να συνδέσετε ένα στιγμιότυπο της συγκεκριμένης κατηγορίας σωλήνα στο κατάλληλο περιβάλλον.

Η class-validator Το πακέτο καθιστά δυνατή την επικύρωση διακοσμητών και μη διακοσμητών, χρησιμοποιώντας validator.js εσωτερικώς. Ενώ το class-transformer Το πακέτο καθιστά δυνατή τη μετατροπή αντικειμένων σε παράδειγμα μιας κλάσης, τη μετατροπή της κλάσης σε αντικείμενο και τη σειριοποίηση ή την αποσειροποίηση αντικειμένων με βάση ορισμένα κριτήρια.

Οι οκτώ σωλήνες που παρέχονται από τη Nest είναι:

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

Για να δείξουμε την επικύρωση στο Nest σε αυτόν τον οδηγό, θα χρησιμοποιήσουμε το ενσωματωμένο ValidationPipe που καθιστά δυνατή την επιβολή επικύρωσης σε ωφέλιμα φορτία αιτήματος και συνδυάζεται καλά με το class-validator πακέτο; συγκεκριμένοι κανόνες δηλώνονται με απλούς σχολιασμούς σε δηλώσεις αντικειμένου μεταφοράς δεδομένων/τοπικών κλάσεων σε κάθε ενότητα.

Για να ξεκινήσετε να χρησιμοποιείτε το ενσωματωμένο ValidationPipe το οποίο εξάγεται από @nestjs/common, ας εγκαταστήσουμε το class-validator και class-transformer πακέτα:

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

Στη συνέχεια, μεταβείτε στην επιλογή main.ts που θα δέσουμε 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());
  await app.listen(3000);
}

bootstrap();

Στη συνέχεια, στις δηλώσεις αντικειμένου μεταφοράς δεδομένων κάθε ενότητας, προσθέτουμε μερικούς κανόνες επικύρωσης δηλώνοντας τους κατάλληλους ελέγχους δεδομένων για κάθε μεμονωμένο δεδομένα. Στην περίπτωσή μας, θα δηλώναμε κατάλληλους κανόνες επικύρωσης για name και email in UpdateUserDto:



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

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

  @IsEmail()
  email: string;
}

Η @IsString() ο διακοσμητής ελέγχει εάν ένα δεδομένο δεδομένα είναι πραγματική συμβολοσειρά και το @IsEmail() Ο επικυρωτής ελέγχει εάν ένα δεδομένο δεδομένο είναι μήνυμα ηλεκτρονικού ταχυδρομείου, διαφορετικά επιστρέφει ψευδές και δημιουργεί μια εξαίρεση.

Τώρα, αν επιχειρήσουμε να κάνουμε ένα PATCH αίτημα σε ένα προφίλ χρήστη και εισαγάγετε έναν αριθμό αντί για ένα έγκυρο email, για παράδειγμα, θα γίνει μια εξαίρεση:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Με αυτά, έχουμε μια πολύ ωραία επικύρωση στην εφαρμογή Nest μας.

Κατά την επικύρωση με ValidationPipe, είναι επίσης δυνατό να φιλτράρουμε τις ιδιότητες μας που δεν θέλουμε να λάβει ο χειριστής μεθόδων μας. Για παράδειγμα, αν ο χειριστής μας περιμένει μόνο name και email ακίνητα, αλλά ένα αίτημα περιλαμβάνει επίσης α country ιδιοκτησία, μπορούμε να αφαιρέσουμε το country ιδιότητα από το αντικείμενο που προκύπτει με ρύθμιση whitelist προς την true όταν στιγματίζουμε 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();

Δέσμευση σωλήνων σε επίπεδο παραμέτρου μεθόδου

Οι σωλήνες μπορούν επίσης να οριστούν σε params, επισης. Για αυτό, θα δέσουμε τον σωλήνα στο επίπεδο παραμέτρων της μεθόδου.

Πριν από τώρα, παρόλο που ορίσαμε το userId για να είναι αριθμός, θα παρατηρήσετε ότι εάν κάνουμε ένα αίτημα με το userId ως συμβολοσειρά, αποδεικνύεται επιτυχημένο ανεξάρτητα από:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Για να διασφαλιστεί ότι η αξία του userId πρέπει πάντα να είναι ένας αριθμός, θα το δηλώσουμε δεσμευτικό το getUser() χειριστής μεθόδου με έλεγχο επικύρωσης που διασφαλίζει το ίδιο:


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

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


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

Η ParseIntPipe ορίζει τον ενσωματωμένο σωλήνα ParseInt και διασφαλίζει ότι τα δεδομένα στα οποία εκτελείται πρέπει να είναι ακέραιος.

Τώρα, όταν κάνουμε ένα GET αίτημα σε μη έγκυρο userId της συμβολοσειράς "ab", η επικύρωση αποτυγχάνει και μια εξαίρεση ρίχνεται με a 400 κωδικός κατάστασης:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Αλλά με μια αριθμητική τιμή, η επικύρωση περνά με επιτυχία:

Οδηγός για το Nest.js - Δημιουργία REST API με Nest και Node PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

Μπορούμε επίσης να ενημερώσουμε άλλους χειριστές μεθόδων ανάλογα για να διασφαλίσουμε τη σωστή επικύρωση:



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

Τώρα, έχουμε εξασφαλίσει την τεχνική βέλτιστης πρακτικής για την επικύρωση δεδομένων που εισέρχονται στην εφαρμογή μας, ίσως από εξωτερική πηγή, ανά πάσα στιγμή.

Συμπέρασμα

Σε αυτόν τον οδηγό, μπορέσατε να μάθετε για το πιο πρόσφατο παιδί στο μπλοκ Node.js. Nest.js και όλα όσα απαιτούνται για να σας βοηθήσουν να ξεκινήσετε, εάν θέλετε να δημιουργήσετε μια εφαρμογή με αυτό. Έχετε μάθει τι είναι το Nest, τις δυνατότητές του, πώς να δημιουργήσετε ένα έργο Nest, πώς να χειρίζεστε τα εισερχόμενα δεδομένα σε μια εφαρμογή Nest και πώς να επικυρώνετε τα εισερχόμενα δεδομένα. Συνολικά, έχετε μάθει για τα δομικά στοιχεία οποιασδήποτε εφαρμογής Nest και την αξία που φέρνει κάθε στοιχείο σε μια εφαρμογή Nest.js.

Από αυτό το σημείο, υπάρχουν ακόμα τόσα πολλά να μάθετε σχετικά με τη δημιουργία μιας εφαρμογής εταιρικής ποιότητας με το Nest, αλλά καταφέρατε να καλύψετε με επιτυχία θεμελιώδεις έννοιες που μπορούν να σας βοηθήσουν να αντιμετωπίσετε όλα όσα έχετε μπροστά σας.

Προσέξτε για έναν νέο οδηγό στο μέλλον, όπου μαθαίνουμε πώς να δημιουργήσουμε ένα ξεκούραστο API με το Nest και τη MySQL.

Ευχαριστώ για την ανάγνωση!

Επιπρόσθετοι πόροι

Έγγραφα Nest.js
Angular Docs

Σφραγίδα ώρας:

Περισσότερα από Stackabuse