Посібник із Nest.js – створення REST API за допомогою Nest і Node PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Посібник із Nest.js – створення REST API за допомогою Nest і Node

Як бекенд-розробник Node.js ви погодитеся, що за замовчуванням Node.js є дуже простим і не робить жодних припущень щодо того, що вам потрібно під час створення програми. У результаті ви відповідаєте за налаштування всього, що ви хочете використовувати в програмі, включаючи обробку маршрутизації, здійснення викликів API, налаштування TypeScript або веб-сокетів або навіть такі фундаментальні речі, як організація коду, структура файлів і правила іменування .

Управління великомасштабною програмою може бути важким завданням, особливо якщо вона не розроблена з чіткою структурою та суворими правилами організації коду.

Nest.js намагається вирішити деякі з цих проблем, створюючи абстракцію навколо Node.js, щоб ви як розробник могли зосередитися на проблемі програми, а не на інших дрібних деталях реалізації.

У цьому посібнику ви ознайомитеся з основними основами Nest.js згори донизу, щоб пришвидшити роботу, щоб ви могли миттєво створювати програми Node.js корпоративного рівня за допомогою Nest.js.

Усе, про що ми дізнаємося за допомогою цього посібника, буде поступовим; охоплюючи багато основи щодо вступних понять. Щоб отримати максимальну віддачу від цього посібника, це допоможе кодувати разом.

Давайте зануримося прямо, люди!

Вихідний код: Як завжди, ви можете розгалужувати вихідний код, розміщений на ньому GitHub.

Примітка: Ми будемо використовувати Postman для тестування API в нашій демонстрації. Ви можете завантажити його на Листоноша Сторінка завантаження. Крім того, ви можете просто використовувати браузер, командний рядок curl або будь-який інший інструмент, з яким ви можете бути знайомі.

Що таке Nest.js

Подумайте про Nest.js як про надмножину Node.js, яка абстрагує складні завдання, інструменти та шаблонний код, а також додає повноцінний набір інструментів для розробки додатків за допомогою сучасних JavaScript і TypeScript.

Nest.js надає готову архітектуру додатків, яка дозволяє розробникам і командам створювати високомасштабовані, тестовані, слабко пов’язані та легко підтримувані, використовуючи легкодоступні та відомі опції та модулі в спільноті, як ті, що доступні в Програми Express.js. Ви навіть можете замінити Express (який він використовує під капотом за замовчуванням) на Fastify, але це означало б, що вам може знадобитися використовувати різні бібліотеки, сумісні з Fastify, у вашому додатку.

Він поєднує в собі функції функціонального програмування, об’єктно-орієнтованого програмування та функціонального реактивного програмування, а також має понад 52.4 тисячі зірок і 6.2 тисячі розгалужень. GitHub і щотижнева кількість завантажень до 1,784,004 XNUMX XNUMX, прогресивний фреймворк Node.js є популярним інструментом для створення ефективних, масштабованих і корпоративних програм на стороні сервера.

Особливості Nest.js

Нижче наведено причини, чому Nest.js став таким популярним фреймворком Node.js:

  1. Nest.js було створено, щоб допомогти розробникам створювати як монолітні програми, так і мікросервіси.
  2. Хоча він потужний, він також зручний для розробників; простий у використанні, швидкий у навчанні та простий у застосуванні.
  3. Він використовує TypeScript (надмножину JavaScript) із коробки та дає місце розробникам для написання супроводжуваного коду без помилок виконання.
  4. Він має інтерфейс командного рядка, який допомагає підвищити продуктивність розробників і полегшити розробку.
  5. Під час створення за допомогою Nest.js процеси розробки вдосконалюються та економиться час, незалежно від того, чи ви завантажуєте мінімально життєздатний продукт, чи працюєте над програмою, оскільки 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 Профіль дозволяє стежити за змінами в додатку та автоматично перезавантажувати його без необхідності зупиняти та перезапускати додаток – і він призначений для розробки. The start:prod сценарій корисний, коли ви хочете перевірити, чи ваша програма готова до виробництва, а також коли ви розгортаєте його у виробництві разом з іншими сценаріями для тестування програми Nest.js.

@nestjs/platform-express визначає експрес як стандартний HTTP-сервер у програмі Nest.

/tsconfig.json

Команда tsconfig.json файл — це файл, написаний у JSON (об’єктна нотація JavaScript), який визначає параметри, пов’язані з 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. Вертикальний пошук. Ai.

Ми можемо змінити вміст, який відображається на 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. Вертикальний пошук. Ai.

Це тому, що ми ще не визначили маршрут для базової URL-адреси програми Nest.

Ще в app.module.ts, у нас є AppModule клас, який ми маємо, ще не є модулем Nest. Щоб зробити його модулем Nest, ми додаємо @Module() декоратор, який імпортується з @nestjs/commonпотім ми передаємо порожній об'єкт.



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

export class AppModule {}

Тепер у нас є модуль Nest.js!

Примітка: Модуль — це клас, який позначено анотацією @Module() декоратор.

Кожна програма Nest має кореневий модуль, який служить точкою входу для визначення структури та зв’язків програми Nest.

Настійно рекомендується використовувати кілька модулів для організації компонентів програми.

Команда @Module() декоратор дозволяє розробникам визначати метадані про клас у програмі Nest.

У випадку, коли є кілька модулів, наприклад модуль користувачів, модуль замовлень, модуль чату тощо, app.module.ts слід використовувати для реєстрації всіх інших модулів програми Nest.

Створення маршрутів; Контролери

Контролери потрібні для створення маршрутів у програмах Nest. Мета контролера — отримувати конкретні запити для програми Nest; контроль циклу запитів і відповідей для різних маршрутів у програмі.

Коли від клієнта до програми Nest надсилається HTTP-запит, маршрут, який відповідає маршруту, за яким робиться запит, обробляє запит і повертає відповідну відповідь.

Щоб створити контролер у додатку 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. Вертикальний пошук. Ai.

Хм, тут ми повертаємо лише рядок, але що, якби ми хотіли повернути об’єкт? Замість рядка ми можемо визначити об’єкт:



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. Вертикальний пошук. Ai.

Подалі від базового маршруту, як щодо створення маршруту, подібного до 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. Вертикальний пошук. Ai.

Ви можете запитати, а що, якщо я хочу робити більше, ніж повертати дані? Можливо, щоб відправити дані.

Для цього вам потрібно вставити дані в метод route, як показано:

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 і фактично вчитися це!

Посібник із Nest.js – створення REST API за допомогою Nest і Node PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Динамічна маршрутизація з параметрами маршруту

Припустімо, ви хочете прийняти динамічні дані як частину запиту. Спочатку нам потрібно визначити маркер на шляху маршруту, щоб відзначити динамічну позицію на маршруті/URL, а потім за допомогою @Param() decorator, параметр маршруту можна отримати так:

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. Вертикальний пошук. Ai.

Обробка асинхронних запитів

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-адресу. The @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;
  }
}

Обробка запитів UPDATE

Запит на оновлення певних даних на сервері можна обробити за допомогою @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. Вертикальний пошук. Ai.

Щоб зберегти папку проекту навіть охайнішою, ніж зараз, ми можемо визначити a 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 дозволяє легко (г)генерувати (мо)дули та (ко)контролери за допомогою 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 клас. У цьому конструкторі ми надаємо private 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.

Демістифікація ін’єкції залежностей у Nest.js

Під час створення менших компонентів програми, таких як клас або модуль, ваш клас може залежати від функціональних можливостей іншого класу або модуля, наприклад, потреби підключатися до служби HTTP, наданої іншим класом, щоб здійснювати виклики API, або рівні обслуговування, які взаємодіють з рівнем збереження.

Залежності можуть бути надані в контролерах через ін'єкційна залежність.

Впровадження залежностей — це концепція та шаблон програмування, які виражають, як частини програми доставляються до інших частин програми, які їх потребують, таким чином, щоб забезпечити високу зв’язність, але слабкий зв’язок.

Nest підтримує впровадження залежностей, і ви можете використовувати його у своїх програмах Nest, щоб підвищити модульність свого проекту.

Практична ілюстрація зображена так:

Припустимо, що клас A використовує деякі функції класу B. Тоді кажуть, що клас A залежить від класу B. Таким чином, щоб використовувати клас B у класі A, нам потрібно спочатку створити екземпляр класу B (тобто створити Об'єкт класу В): const b = new B ().
Передача завдання створення екземпляра класу до іншого класу та безпосереднього використання залежності в наданому класі (компонент інжектора) відома як ін’єкція залежностей.

Поради: Впровадження залежностей, або DI, є однією з фундаментальних концепцій таких фреймворків, як Spring Boot, Nest.js і Angular.js. Якщо ви хочете прочитати більше про це, ви можете перевірити офіційна документація Angular.

Як правило, клас повинен зосереджуватися виключно на виконанні своїх функцій, а не використовуватися для створення різних об’єктів, які йому можуть бути потрібні чи ні.

Переваги впровадження залежностей.

  1. Це допомагає з модульним тестуванням.
  2. За допомогою ін’єкції залежностей шаблонний код зменшується, оскільки ініціалізація залежностей виконується компонентом інжектора.
  3. Процес розширення заявки стає легшим.
  4. Ін’єкція залежностей допомагає ввімкнути слабий зв’язок.

Вивчення корисних навантажень запитів

Пам’ятайте, що в різних обробниках запитів, таких як POST і PATCH, ми змогли підключитися до запиту, надісланого сервером за допомогою @Req() декоратор. Однак це ще щось.

Замість того, щоб отримувати весь об’єкт запиту, ми можемо просто торкнутися окремих частин об’єкта запиту, які нам потрібні.
Таким чином, Nest надає різні декоратори, які можна використовувати з обробниками маршрутів HTTP для доступу до об’єктів Express або Fastify:

Декоратори гнізд Об’єкт Fastify або Express, до якого здійснюється доступ
`@Request(), @Req()` `req`
`@Response(), @Res()` `re“s`
`@Next()` `наступний`
`@Session()` `req.session`
`@Param(param?: рядок)` `req.params` / `req.params[param]`
`@Body(параметр?: рядок)` `req.body` / `req.body[param]`
`@Query(параметр?: рядок)` `req.query` / `req.query[параметр]`
`@Headers(параметр?: рядок)` `req.headers` / `req.headers[param]`
`@Ip()` `req.ip`
`@HostParam()` `req.hosts`

Типовим прикладом може бути заміна @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, але нам потрібно тримати наші коди СУХИМИ (не повторюйте себе), щоб ми не повторювалися в кодовій базі.

Для цього в нову папку /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 package дозволяє перетворювати об’єкти на екземпляр класу, перетворювати клас на об’єкт і серіалізувати або десеріалізувати об’єкти на основі певних критеріїв.

Вісім каналів, наданих Nest:

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

Щоб продемонструвати перевірку в Nest у цьому посібнику, ми використаємо вбудований ValidationPipe що дає змогу застосовувати перевірку корисних навантажень запиту та добре поєднується з class-validator пакет; конкретні правила оголошуються з простими анотаціями в оголошеннях Data Transfer Object/local class у кожному модулі.

Щоб почати використовувати вбудований 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();

Далі в оголошеннях Data Transfer Object кожного модуля ми додаємо кілька правил перевірки, оголошуючи відповідні перевірки даних для кожного окремого. У нашому випадку ми оголосимо відповідні правила перевірки для name та email in UpdateUserDto:



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

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

  @IsEmail()
  email: string;
}

Команда @IsString() декоратор перевіряє, чи дані є справжнім рядком, і @IsEmail() Validator перевіряє, чи дані є електронною поштою, інакше він повертає false і створює виняток.

Тепер, якщо ми спробуємо зробити a PATCH надішліть запит до профілю користувача та введіть число замість дійсної електронної пошти, наприклад, буде створено виняток:

Посібник із Nest.js – створення REST API за допомогою Nest і Node PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Завдяки цьому ми маємо дуже гарну перевірку в нашому додатку Nest.

Під час перевірки с ValidationPipe, також можна фільтрувати наші властивості, які ми не хочемо, щоб наш обробник методів отримував. Наприклад, якщо наш обробник лише очікує name та email властивості, але запит також включає a 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. Вертикальний пошук. Ai.

Щоб переконатися, що значення 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 і гарантує, що дані, з якими він працює, мають бути цілими числами.

Тепер, коли ми робимо a GET запит до недійсного userId рядка «ab», перевірка не вдається, і створюється виняток за допомогою a 400 код статусу:

Посібник із Nest.js – створення REST API за допомогою Nest і Node PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Але з числовим значенням перевірка проходить успішно:

Посібник із Nest.js – створення REST API за допомогою Nest і Node PlatoBlockchain Data Intelligence. Вертикальний пошук. Ai.

Ми також можемо відповідно оновити інші обробники методів, щоб забезпечити належну перевірку:



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