Соглашения и паттерны
Этот раздел описывает повторяющиеся паттерны кода. Понимание этих соглашений — ключ к тому, чтобы добавлять новые фичи «в том же стиле».
1. Структура доменной библиотеки
Заголовок раздела «1. Структура доменной библиотеки»Каждый домен в libs/apis/providers/<service>/ делится на два вида проектов Nx:
providers/<service>/├── data-access/ # Один проект: DTO, константы, типы, интерфейсы│ └── src/lib/{dtos,constants,types,interfaces}/└── features/<feature>/ # Проект на фичу: модуль + логика └── src/lib/ ├── <feature>.module.ts ├── <feature>.controller.ts ├── <feature>.service.ts └── <feature>.repository.tsdata-accessне содержит контроллеров и сервисов — только контракты данных. Его импортируют и фичи, и другие сервисы.features/*— самодостаточные NestJS-модули, экспортируемые через барельsrc/index.ts.
2. Слои внутри фичи
Заголовок раздела «2. Слои внутри фичи»Controller → Service → Repository → PrismaClientService / RedisClient / RabbitClient (HTTP) (логика) (доступ к БД) (инфраструктура)- Controller — только маршрутизация, guard’ы, извлечение данных из запроса (через декораторы), вызов сервиса. Без логики.
- Service — бизнес-правила, оркестрация, транзакции.
- Repository — инкапсулирует запросы Prisma/Redis. Именно здесь
PrismaClientService.
Не в каждой фиче есть все три слоя (простые фичи могут обходиться без repository), но направление зависимостей всегда сверху вниз.
3. Именование файлов
Заголовок раздела «3. Именование файлов»| Суффикс | Назначение |
|---|---|
*.module.ts | NestJS-модуль |
*.controller.ts | HTTP-контроллер |
*-core.module.ts | «Ядровый» модуль без контроллеров — переиспользуемый набор провайдеров (сервис+репозиторий), который импортируют другие модули |
*.service.ts | Сервис с логикой |
*.repository.ts | Доступ к данным |
*.strategy.ts | Passport-стратегия |
*.guard.ts | Guard авторизации |
*.dto.ts | DTO (валидация + сериализация) |
*.type.ts / *.interface.ts | Типы/интерфейсы |
*.constants.ts | Константы (имена стратегий, ключи Redis и т.п.) |
*.env.ts / *.validation.ts / *.config.ts | Конфиг-модуль (см. ниже) |
Паттерн *-core.module.ts vs *.module.ts
Заголовок раздела «Паттерн *-core.module.ts vs *.module.ts»Часто фича имеет xxx-core.module.ts (экспортирует сервис/репозиторий, без контроллеров) и xxx.module.ts (импортирует core + подключает контроллеры). Это позволяет другому сервису переиспользовать логику без HTTP-слоя.
4. Алиасы путей (Nx / TypeScript)
Заголовок раздела «4. Алиасы путей (Nx / TypeScript)»Импорты идут через алиасы из tsconfig.base.json, а не по относительным путям:
import { CustomerAuthModule } from '@crewsforge-back/apis/providers/auth-api/features/customer-auth';import { PrismaClientService } from '@crewsforge-back/apis/utils/prisma-client';import { PrismaExceptionFilter } from '@crewsforge-back/apis/shared';Каждый lib-проект экспортирует публичный API через src/index.ts (барель). Импортировать внутренние файлы напрямую нельзя — только то, что реэкспортировано из index.ts.
5. DTO, валидация и сериализация
Заголовок раздела «5. DTO, валидация и сериализация»- Глобальный
ValidationPipeсtransform: trueиtransformOptions.strategy = 'excludeAll'— значит в ответ попадают только поля, помеченные@Expose()(безопасно по умолчанию). - У части сервисов дополнительно
whitelist: true/forbidNonWhitelisted: true— отсекают лишние поля во входе. - Маппинг сущность → DTO делается через общий
MapperService(libs/apis/shared, на базеclass-transformer).
6. Конфигурация (env)
Заголовок раздела «6. Конфигурация (env)»Каждый конфиг — отдельный Nx-проект в libs/apis/configs/ из 4-5 файлов:
<config>/src/lib/├── <config>.env.ts # маппинг process.env → объект├── <config>.validation.ts # Joi-схема валидации├── <config>.config.ts # registerAs(...) namespace├── <config>-config.service.ts # типизированный сервис-обёртка└── <config>-config.module.ts # ConfigModule.forFeature(...)Сервисы инжектят типизированный XxxConfigService вместо process.env. Полный список переменных — в configs.
7. Транзакции и контекст запроса
Заголовок раздела «7. Транзакции и контекст запроса»В каждом приложении подключён ClsModule.forRoot(...) с ClsPluginTransactional:
- Транзакции объявляются декларативно (через
@Transactional()в сервисах) и живут в CLS-контексте запроса. X-Request-Idберётся из заголовка или генерируется (uuid) — сквозная трассировка.
8. Авторизация
Заголовок раздела «8. Авторизация»- JWT access/refresh, стратегии passport по типу пользователя (customer/employee/admin).
- Guard’ы и декораторы (
@Token(),@HeaderFingerprint(),@HeaderSessionId()) — в shared-lib. - Refresh-токены передаются через httpOnly cookie (
cookie-parser+cookie.helper).
9. Обработка ошибок
Заголовок раздела «9. Обработка ошибок»Глобальный PrismaExceptionFilter (libs/apis/shared) маппит ошибки Prisma (например, нарушение уникальности) в корректные HTTP-статусы. Подключается в main.ts каждого сервиса.
Чек-лист «добавить новую фичу»
Заголовок раздела «Чек-лист «добавить новую фичу»»- Создать DTO в
data-accessнужного сервиса (@Expose()на выходных полях). - Создать
features/<feature>/сmodule/controller/service/(repository). - Экспортировать модуль через
src/index.ts. - Добавить алиас в
tsconfig.base.json(если Nx-генератор не сделал сам). - Подключить модуль в
apps/<service>/src/app/app.module.ts. - Guard’ы и маппинг брать из
shared, конфиги — изconfigs.