NestJS / 38 минут
CLI и первый проект NestJS
Создайте проект CLI и проследите запуск Nest-приложения до HTTP-ответа.
- Создайте проект 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» обычно указывает на несогласованную регистрацию или область видимости, а не на необходимость случайно сделать всё глобальным.
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 тоже является публичным контрактом и требует осознанного состава данных.
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-приложения и подходит для проверки провайдеров или консольного сценария. Это разные способы запуска с разной инфраструктурой, а не взаимозаменяемые названия одной функции.
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 и тесты следующих глав.