Skip to content

Implementation of the main functions of Nest.js with a detailed explanation and infographics. Also added examples with Sitemap, integrating a third-party API or adding third-party services such as Telegram bots or the like

Notifications You must be signed in to change notification settings

pestsov-v/nest.js-shorts

Repository files navigation

Nest.js

Архитектура Nest.js

Nest.js/CLI

nest new

nest new - позволяет создать новый сервис, API или любое другое приложение и дополнительные опции. Если не передать name, то СLI спросит какое имя у проекта.

Команда nest new <name> [options] - создаёт новый проект с именем <name>. Опции при этом могут быть следующими:

  • --dry-run - создать проект без реальных изменений.
  • --skip-git - создать проект без ининциализации git репозитория.
  • --skip-install - создать проект без установки зависимостей.
  • --package-manager - выбрать менеджер пакетов (может быть или npm или yarn).
  • --language - выбрать язык программирования, который будет использоватся в проекте (может быть или TS или JS).

nest generate

nest generate - позволяет создать новый компонент к уже существующему репозиторию по некоторой схеме. Схема это например контроллер, сервис или т.п., с некоторым именем.

Команда nest generate <schematic> <name> [options] - создаёт компонент по схеме c именем :

  • --dry-run - создать компонент без реальных изменений.
  • --project - выбор проекта для monorepo.
  • --flat - создаёт компонент без вложенной папки.
  • --spec - создаёт файл тестов.
  • --no-spec - не создавать файл тестов.

nest build

nest build - позволяет собрать проект для production мода.

Команда nest build - собирает production вариант приложения, с некоторыми опциями:

  • --path - путь до tsconfig.json если он кастомизирован, по умолчанию он будет лежать в корне проекта.
  • --config - путь до nest-cli.json, аналогично с tsconfig.json.
  • --watch - пересобирать проект при появлении каких-либо изменений.
  • --webpack - использовать webpack для сборки.
  • --webpackPath - указать путь до webpack.
  • --tsc - собрать проект с помощью tsc.

nest start

nest start - использует те же опции, что и nest build, но и ещё с дополнительными опциями.

Команда nest start имеет допольнительные, следующие, опции:

  • --preserveWatchOutput - не очищать консоль при сборке.
  • --watchAssets - следит не только за ts файлами.
  • --debug - режим debug, полезен при отладке приложения.
  • --exec - путь до bin файла в node.

Модули

Модули - это по сути строительные блоки из которых состоит приложение. В обязательном у каждого приложения на Nest.js есть хотя бы один модуль - корневой модуль, который часто называется appModule. Рекомендуется разделять модули по доменным областям.

image.jpg

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

Модуль объеденяет зависимости одной доменной области

image.jpg

Суммарно зависимости, которые скрывает за собой модуль это:

  • импорты. Это другие модули, которые текущий модуль импортирует в себя.
  • контроллеры. Это http или другие протоколы контроллеры, которые позволяет взаемодействвоать с приложением.
  • провайдеры. Это различные сервисы, репозитории баз данных и другие провайдеры, которые могут быть задаными.
  • экспортс. Это то, что будет экспортировано. Это могут быть или провайдеры, которые будут переиспользоватся в других модулях или это реэкспорт других модулей, которые он в себя импортирует.

Это всё хранится в декораторах, поскольку когда приложение запускается, оно начинает строить дерево зависимостей идя от корневого модуля, он собирает все импорты, провайдеры и контроллеры и строит это дерево.

Использование модулей

Первый способ - общие модули

Общие модули можно импортировать в различные модули.

image.jpg

Второй способ - повторный экспорт модулей

Это когда модуль используйщийся промежуточным модулем используется ниже

image.jpg

Третий способ - глобальные модули

Такое может быть необходимо тогда, когда есть модуль, который необходимо использовать во всех модулях приложения. К примеру если используется подключение в базе данных во всех модулях, то можно задать модуль работы базы данных как глобальный и использовать репозиторий базы данных везде без дополнительного импорта модулей. Единственное это то, что глобальный модуль должен быть импортирован в корневой модуль.

image.jpg

Четвертый способ - динамические модули

Часто, особенно при работе с базой данных, необходимо не только получить модуль базы данных, но и передать туда какую-то информацию о подключениях, пользователях и т.п., тогда необходимо использовать динамические модули. Динамические модули - это статический метод модуля, который, в результате, возвращает модуль с вложением провайдера, экспорта и импорта. По умолчанию их необходимо называть forRoot, если это глобальный или же forFeature если этот модуль использоватся в определенном скоупе модулей.

image.jpg

Контроллеры

Контроллер это входная точка приложения - то место, куда приходят запросы HTTP, MQTT, RabbitMQ, Kаfka и т.д.

image.jpg

Пример контроллера:

image.jpg

Например у нас есть ссылка: http://host.ru/api/product/add/1.

  • Первое что нужно понимать, что на уровне приложения можно задать глобальный префикс апи, с помощью app.setGlobalPrefix(<api_value>). Это очень удобно, поскольку, если у нас на одном домене лежит и фронт и бэк, то фронт будет стучатся на бэк по отдельно выделенному, глобальному, маршруту.
  • Второе это роутинг, который определяется уже в АПИ. Контроллеры это классы, которые декорированы, декоратором Controller. Внутрь этого декоратора мы можем передать путь по которому он будет доступен.
  • Третье это методы. Они должны быть декорированы соответствующим типом http запроса.

Типы декораторов контроллера

Типы декораторов:

  • @Req() - это собственно request или req из js. Является объектом запроса.
  • @Res() - это собственно response или res из js. Является объектом ответа.

Декораторы, которые можно вытянуть через объект запроса (@Req()):

  • @Params(key?: string) - строковый параметр запроса, это может быть например ID.
  • @Body(key?: string) - тело запроса.
  • @Query(key?: string) - query параметры запроса.
  • @Headers(name?: string) - заголовки запроса.
  • @Session() - сессия пользователя.

Разбор декораторов

image.jpg

Дополнительные возможности контроллера

1.jpg

  • Реагирования на Wildcard. Это способность помечать места, где можно вставлять любые символы или символы с заданой политикой.
  • Свои кастомизированные HTTP коды.
  • Свои кастомизированные заголовки.
  • Редиректы. В принципе необходимо только в MVC приложениях. В остальных случаях, при перенаправлениях на React или другие фреймворки фронтэнда, то он будет ругатся на CORS.

2.jpg

  • Ограничение по поддомену. Если очень большое API, то это можно разграничить с помощью ограничений по поддомену.
  • Возврат Promise или Observable. Мы можем вернуть не только строку, но и ещё Promise или Observable, то есть Nest.js сам разрезолвит Promise и вернёт его как ответ.

Объект ответа

Res.jpg

Помимо того, что мы можем вернуть ответ с помощью return, мы можем его вернуть с помощью res. Им можно отправить статус, файл и т.д. Важно понимать, что этот response это не нодовский response. Это response именно express'а.

Провайдеры

Провайдеры это клас, который позволяет использовать модель Nest.js по внедрению зависимостей и встраиватся друг в друга, в контроллеры, в сервисы и выполнять те или иные функцию, например чтение из базы данных или запрос к другим сервисам.

Простой сервис

Самый простой вид сервиса состоит из класса, в котором есть методы и на который навешан декоратор @Injectable.

image.jpg

@Injectable как раз и указывает, что он может быть использован в качестве провайдера и участвовать в дереве зависимостей. Чтобы использовать такой сервис, его достаточно вставить в провайдер модуль providers и затем в контроллере в конструктор, добавить этот сервис.

использование зависимости

Как только будет создаватся инстанс контроллера, в него будет уже внедрена зависимость от сервиса и его можно будет использовать. Если же необходимо использовать провайдер не в том модуле, в котором он был вставлен, то нужно его экспортить, для того чтобы из этого модуля был доступен этот сервис. Любой модуль который импортирует модуль с экспортируемым сервисом также сможет его использовать.

Типы провайдеров

  • Класс - это провайдер используется как класс.
  • Фабрика - это проовайдер, который сформирует фабрику, который при необходимости будет формировать нам класс.
  • Величина - это конкретное значение, которое можно использовать, например строка подключения.
  • Переназывание использующегося провайдера и использовать его с другим псевдонимом.

useClass

На самом деле в модуль providers записывается не только название самого сервиса, но и его тип - useClass. provide означает, как будет называтся эта зависимость.

useClass.jpg

useValue

Аналогично с useClass можно развернуть модуль провайдеров на его название и на его тип. Также необходимо будет провайдить инстанс класса, но его значение можно поменять на величину. Это очень полезно, когда необходимо писать тесты. Например, какой-то сервис должен доставать продукты из базы данных и вместо того, чтобы ходить в реальную базу данных, useValue позволяет имитировать это хождение в базу данных, замення провайдер на величину.

useValue.jpg

Также useValue используется в решениях, где DI реализовывается без класса.

DI-without-class.jpg

В этом случае используется строковое значение, это значение должно быть уникальным иначе это вызовет колизию в приложении. Используется он чуть сложнее, чем класс, поскольку в тех местах, где он будет использоваться необходимо применять декоратор @inject, и передавать туда строку, которая равна уникального значения и как само значение будет использоватся модуль value.

useFactory

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

use-Factory.jpg

useExisting

На практике практически не используется. Используется когда есть существующий провайдер с именем, которое переименовывается и оно же используется.

use-Existing.jpg

Типы Scope выполнения

Существует три Skope выполнения:

  • DEFAUILT
  • REQUEST
  • TRANSIENT

DEFAULT

DEFAUILT - это то, как записывается любой сервис, с пустым @Injectable с пустым декоратором @Injectable. Это означает, что на всё приложение будет один инстанс этого сервера. Это классический паттерн Singlton. Это означает, что если какой-то сервис используется в разных местах какой-то другой сервис, то этот сервис будет один и тот же инстанс этого сервиса.

default.jpg

REQUEST

Порой не устраивает, что на каждый запрос будет один инстанс в дереве зависимостей и необходимо использовать на каждый запрос новый инстанс. Например на каждый запрос будет создан отдельный инстанс какого-то сервиса в определённом сервисе. При этом, если какой-то третий сервис зависит от этого, определённого, сервиса, то он получит один и тот же инстанс. Это может быть нужно, если нужен chainable класс. Например когда последовательно вызываются через точку методы, где каждый раз возвращается сам класс, тогда каждый раз нужно иметь отдельный инстанс, чтобы не иметь конфликтов с записью внутренних параметров в этот сервис.

request.jpg

TANSIENT

Самый редкий случай, когда в различных сервисах используется один сервис, то в каждом из этих сервисов будет отдельный инстанс этого третъего сервиса.

transient.jpg

ExceptionFilter и Pipes

image.jpg

При отправке каких либо запросов на API с клиента - они могут быть преобразованы через Pipes. В свою же очередь перед тем, как отправить данные на клиент, эти данные могут быть изменены за счёт ExceptionFilter'ов.

Exceptions

Когда происходит ExceptionFilter, то под капотом происходит следующее:

Exceptions.jpg

Этот exception преобразовывается Nestjs в JSON. ExceptionFilter позволяют внедрится в процесс обработки между Exception и JSON.

Exceptions-filter.jpg

Для того, чтобы сделать свой фильтр нужно создать класс, который будет инплементировать ExceptionFilter и иметь метод сatch. Также он должен быть навешан декоратором @Catch, в котором должно быть указан какими exception должны быть обработаны эти фильтры. В рамках метода catch он будет принимать два значения:

  • сам exception.
  • host из которого можно получить контекст запроса.

Pipes

В Nestjs есть уже ряд существующих pipe, которые позволяют преобразовывать существующие данные. Первый это ValidationPipe, который занимается валидацией. Он может быть внедрён декоратором UsePipes. Также есть Pipe, которые можно отправить на параметры.

Pipes.jpg

Под капотом ValidationPipe реализовывает библиотеку validator и класс трансформер, который позволяет преобразовывать объект в класс, а дальше валидировать свойства этого класса. Реализовывается он очень просто:

Validation-Pipe.jpg

При этом Nestjs позволяет валидировать и создавать свой pipe. Аналогично другим pipe необходимо имплементировать класс PipeTransform в своём классе и реализовать там метод transorm, который принимает входящие значения, которые он будет реализовывать и метаданные. Методоанные содержат данные о том, где применяется этот pipe, применяется он в body, params или где-то ещё, его базовый тип: строка это или что-то другое.

Custom-pipe.jpg

Глобальное использование

Если необходимо использовать глобальные ExceptionFilter или Pipe, то его необходимо подключить к app:

image.jpg

Interseptors

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

About

Implementation of the main functions of Nest.js with a detailed explanation and infographics. Also added examples with Sitemap, integrating a third-party API or adding third-party services such as Telegram bots or the like

Topics

Resources

Stars

Watchers

Forks

Packages