NestJS / 38 минут

CLI и первый проект NestJS

Создайте проект CLI и проследите запуск Nest-приложения до HTTP-ответа.

В процессе Теория: впереди Практика: впереди Тест: впереди
01 / 14
После этой главы
  • Создайте проект CLI и проследите запуск Nest-приложения до HTTP-ответа.
  • Применить тему в задаче «CLI и первый проект NestJS» и объяснить граничные случаи.

Около 8 минут на чтение и разбор примеров. Практика — отдельно, в своём темпе.

Что добавляет Nest поверх HTTP-платформы

NestJS организует серверное приложение вокруг модулей, провайдеров и явно описанных границ. По умолчанию HTTP-адаптером часто служит Express, но бизнес-сценарий не должен зависеть от всех деталей его req и res. Framework помогает собрать граф зависимостей и применить обработку запроса последовательно. Он не отменяет необходимость понимать HTTP, асинхронность и проверку внешнего ввода.

В проекте JSlab используется Node.js 24 с указанным в package.json минимальным patch-уровнем. Для собственного проекта сначала проверьте требования выбранной версии Nest и установите совместимую среду. Нельзя считать любую установленную на машине версию Node подходящей только потому, что команда node вообще запускается. Lockfile фиксирует зависимости, а настройка среды делает сборку воспроизводимой.

Создание стартовой структуры CLI

Nest CLI генерирует исходную структуру и конфигурацию проекта. Для отдельного учебного API можно выполнить npx с выбранной основной версией CLI, затем выбрать пакетный менеджер. Такой запуск отличается от ручного создания нескольких файлов: генератор добавляет типовые настройки TypeScript, тестирования и команд разработки.

Терминал
npx @nestjs/cli@11 new library-api
cd library-api
npm run start:dev

После генерации найдите main.ts, корневой модуль, controller и service. Прочитайте связь между ними, прежде чем удалять или переименовывать файлы. Декоратор @Controller описывает HTTP-группу, @Injectable — провайдера, @Module — состав и зависимости модуля. Наличие декоратора без регистрации в подходящем графе не делает класс автоматически доступным в любом месте.

Bootstrap и корневой модуль

NestFactory.create получает корневой модуль и строит приложение. Во время инициализации контейнер разрешает зависимости, создаёт провайдеры и связывает маршруты. Ошибка «не удаётся разрешить dependency» обычно указывает на несогласованную регистрацию или область видимости, а не на необходимость случайно сделать всё глобальным.

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

В production-конфигурации порт должен проходить проверку и поступать из согласованного источника. Публичное логирование секретного окружения не помогает диагностике. Обработку ошибки запуска нужно организовать так, чтобы не обслуживать запросы в частично неготовом состоянии и не прятать реальный отказ за успешным сообщением «started».

Первый контроллер

Контроллер определяет HTTP-маршруты и вызывает сценарии. Для простой проверки работоспособности можно вернуть небольшой публичный объект. Не добавляйте в health-ответ строку подключения к БД, секреты или полное окружение. Диагностический endpoint тоже является публичным контрактом и требует осознанного состава данных.

TypeScript
import { Controller, Get, Module } from '@nestjs/common';
@Controller('health')
class HealthController {
  @Get() status() { return { ok: true }; }
}
@Module({ controllers: [HealthController] })
class AppModule {}

Префикс controller и путь метода складываются в итоговый URL. HTTP-метод задаётся декоратором, поэтому @Get и @Post на одинаковом пути остаются разными операциями. Для сложного действия controller должен передать работу сервису, а не собирать в одном методе SQL, авторизацию и отправку письма.

init, listen и application context

Для HTTP-теста можно вызвать app.init и передать app.getHttpServer в Supertest, не оставляя постоянный порт разработчика. createApplicationContext создаёт DI-контекст без HTTP-приложения и подходит для проверки провайдеров или консольного сценария. Это разные способы запуска с разной инфраструктурой, а не взаимозаменяемые названия одной функции.

TypeScript
const app = await NestFactory.create(AppModule, { logger: false });
try {
  await app.init();
  // await request(app.getHttpServer()).get('/health');
} finally {
  await app.close();
}

Закрытие освобождает ресурсы и запускает соответствующий lifecycle. Тест, который получил правильный body, но оставил сервер или подключение открытым, ещё не полностью корректен. В production добавляют согласованное завершение по сигналам и ответственность за собственные фоновые ресурсы приложения.

Практика первого приложения

Задание требует настоящего Nest-приложения с GET /health, init, HTTP-запросом и close. Вернуть заранее созданный объект из solve недостаточно для понимания framework-границы. Сначала соберите маленький модуль и контроллер, затем проверьте полученный статус и JSON. Каждый вызов должен управлять собственным жизненным циклом.

После решения разнесите пример по файлам, сохранив поведение. Затем добавьте сервис с одной зависимостью и объясните, кто его создаёт и где он зарегистрирован. Не переходите к большим «универсальным» архитектурам до понимания этого минимального графа: из него вырастают DTO, guards, interceptors и тесты следующих глав.

Загружаем редактор…
Следующая темаМодули NestJS

Музыка: Reverie — Scott Buckley · CC BY 4.0