Знакомимся с NestJS

от автора

Перевод статьи подготовлен в преддверии старта курса «Разработчик Node.js».


У современных разработчиков есть много альтернатив, когда речь заходит о создании веб-сервисов и других серверных приложений. Node стал крайне популярным выбором, однако многие программисты предпочитают более надежный язык, чем JavaScript, особенно те, кто пришел из современных объектно-ориентированных языков, например, таких как C#, C++ или Java. Если TypeScript просто хорошо подходит NodeJS , то фреймворк NestJS выводит его на совершенно новый уровень, предоставляя современные инструменты бэкенд-разработчику для создания долговечных и высокопроизводительных приложений с использованием компонентов, провайдеров, модулей и других полезных высокоуровневых абстракций.

В этой статье мы рассмотрим процесс создания простого API-сервера на NestJS для обработки базового сценария приложения: создание, хранение и получение списка продуктов универсама.

Если хотите ознакомиться с исходным кодом проекта, вы можете найти его здесь.

Создание проекта

Для работы с Nest нужна среда Node. Если у вас ее еще нет, зайдите на их сайт и скачайте ее.
Установить фреймворк достаточно просто:

$ npm i -g @nestjs/cli

Этот проект был создан с помощью Nest CLI после выполнения следующей команды:

$ nest new nest-js-example

Такая команда создаст совершенно новый проект Nest с необходимыми файлами конфигурации, структурой папок и шаблоном сервера.

Точка входа приложения

Основной файл, который конфигурирует и запускает сервер – это src/main.ts:

import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module';  async function bootstrap() { 	     const app = await NestFactory.create(AppModule);     await app.listen(3000); }  bootstrap();

Этот файл импортирует класс NestFactory, который используется для создания приложения, и основной файл AppModule (с которым мы в скором времени познакомимся), а затем загружает приложение, инстанцируя его, и слушает на 3000 порту.

App Module

Файл, в котором задекларированы компоненты приложения, называется src/app.module.ts:

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

Это файл, где остальные компоненты импортируются и декларируются в Модуль, который импортируется в предыдущем файле (main.ts). Инструменты Nest CLI автоматически обновят этот файл по мере необходимости, когда будет дана команда создать новый компонент. Здесь импортируются контроллер и сервис для items и добавляются в модуль.

Items Controller

Следующий файл, с которым мы ознакомимся – это src/items/items.controller.ts:

import { Controller, Req, Get, Post, Body } from '@nestjs/common' import { CreateItemDto } from './dto/create-item.dto' import { ItemsService } from './items.service' import { Item } from './items.interface'  @Controller('items') export class ItemsController {      constructor(private readonly itemsService: ItemsService) {}      @Post()     create(@Body() data: CreateItemDto): Object {         return this.itemsService.create(data)     }      @Get()     findAll(): Array<Item> {         return this.itemsService.findAll()     } }

Этот файл определяет контроллер для создания item’ов и получения списка ранее созданных. Здесь импортируется несколько ключевых компонентов:

  • CreateItemDto: Объект Data-Transfer, который определяет как данные item’ов будут отправляться по сети (т.е. это структура данных JSON);
  • ItemsService: Provider, который обрабатывает манипуляции или хранение данных Item;
  • Item: Интерфейс, который определяет внутреннюю структуру данных для Item;

Декоратор @Controller('items') указывает фреймворку, что этот класс будет обслуживать конечную точку REST /items, а конструктор ItemsController берет экземпляр ItemsService, который используется внутри для обслуживания двух HTTP методов:

  • POST /items (создает новый item из JSON-запроса);
  • GET /items (получения списка ранее созданных item’ов).

Запросы к этим двум методам обрабатываются методами create и FindAll, которые привязаны к соответствующим методам HTTP с помощью декораторов @Post() и @Get(). Дополнительные методы тоже могут поддерживаться декораторами аналогичным образом, например, @Put() или @Delete() и т.д.

Интерфейсы объекта Item

Дальше разберемся с двумя файлами, которые определяют интерфейсы для хранения item, один для внутреннего использования, такого как проверка типа по время компиляции (Item), и внешний интерфейс для определения ожидаемой структуры входящего JSON (CreateItemDto):

export interface Item { 	     name: string,     description: string,     price: number }
export class CreateItemDto {      @IsNotEmpty()     readonly name: string;      @IsNotEmpty()     readonly description: string;      @IsNotEmpty()     readonly price: number; }

Интерфейс Item определяет три свойства обычного магазинного товара: название, описание и цену. Это гарантирует отсутствие путаницы в архитектуре приложения в вопросах того, что такое item и какими свойствами он обладает.

Класс CreateItemDto отражает свойства Item, декорируя каждое свойство @IsNotEmpty(), чтобы гарантировать, что все эти свойства запрашиваются конечной точкой REST API.

Все свойства обоих классов строго типизированы, что является одним из главных преимуществ TypeScript (отсюда и название). На первый взгляд это повышает уровень понимания контекста, а еще значительно сокращает время разработки при правильном использовании вместе с инструментами анализа кода (такими как IntelliSense в VSCode). Особенно характерно это для больших проектов с сотнями или даже тысячами различных классов и интерфейсов. Для тех, кто не обладает совершенной фотографической памятью с бесконечной емкостью (например, для меня), так гораздо проще, чем пытаться запомнить тысячи конкретных деталей.

Сервис Items

Самый последний – сервис для создания и получения items: items.service.dart:

import { Injectable } from '@nestjs/common' import { Item } from './items.interface'  @Injectable() export class ItemsService {      private items: Array<Item> = []      create(item: Item): Object {          this.items.push(item)          return { id: this.items.length.toString() }     }      findAll(): Array<Item> {          return this.items;     } }

Класс ItemsService определяет простой массив объектов Item, который будет служить в качестве in-memory хранилища данных для нашего проекта-примера. Два метода, которые пишут и читают из этого хранилища это:

  • create (сохраняет Item в список и возвращает его id);
  • findAll (возвращает список ранее созданных объектов Item).

Тестируем

Чтобы запустить сервер, используйте стандартную команду npm run start. Когда приложение запущено, его можно протестировать с помощью отправки HTTP-запросов через CURL:

$ curl -X POST localhost:3000/items -d '{"name":"trinket", "description":"whatever", "price": 42.0}'

Выполнение этой команды вернет ответ в формате JSON с id созданного item. Чтобы показать список item’ов, которые уже созданы используйте:

$ curl localhost:3000/items

GET-запрос к /items, приведенный выше, вернет ответ в формате JSON с информацией об item’ах, которые уже хранятся в памяти. Ответ должен выглядеть как-то так:

[{"{\"name\":\"trinket\", \"description\":\"whatever\", \"price\": 42.0}":""}]

Заключение

NestJS относительно новое решение в области бэкенд-разработки, с большим набором функций для быстрого построения и развертывания корпоративных сервисов, которые отвечают требованиям современных клиентов приложений и придерживаются принципов SOLID и приложения двенадцати факторов.

Чтобы узнать больше, посетите сайт NestJS.
Спасибо, что ознакомились с моей статьей. Счастливого кодинга!

ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/493090/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *