У современных разработчиков есть много альтернатив, когда речь заходит о создании веб-сервисов и других серверных приложений. 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/
Добавить комментарий