6.8 KiB
Backend HTTP API
Выбор boundary
Сначала определи, меняется wire contract или только реализация существующего use case. Для route/request/response/status/error shape используй локальный публичный контракт и configured HTTP tests.
| Проверка | Где выполнять |
|---|---|
| Тип/формат/диапазон входа | Runtime DTO class с class-validator/class-transformer |
| Согласованность полей, бизнес-ограничение | Feature service/domain helper |
| Session и identity | Existing guard/strategy |
| Доступ user к конкретному account | Existing access service |
| HTTP envelope/безопасная ошибка | Общий HttpExceptionFilter |
Controller объявляет contract и делегирует; не обращается напрямую к Prisma/gRPC
и не выполняет финансовые расчёты или сложную оркестрацию.
Controller вызывает application use case/service. Identity берётся из verified
request.user, не из body/userId, предоставленного клиентом. Access rules активируют Security.
DTO и errors
DTO — runtime class: TS interface не предоставляет validation metadata.
*.controller.ts и *.dto.ts остаются около HTTP boundary, в root компактного
module или presentation. DTO можно передать application boundary при совпадении
формы; отдельный Input с теми же полями не нужен. Domain не импортирует DTO:
например, чистые денежные расчёты используют Money, а Swagger — MoneyDto.
Нормализованная форма input нужна только при смысловом отличии от wire contract;
выбор suffix принадлежит Architecture.
ValidationPipe уже настроен в configureApp (transform, whitelist).
Не обещай rejection неизвестных fields: forbidNonWhitelisted не включён.
Для query numbers/arrays выбирай явное преобразование и валидаторы, как в
operations DTO. Swagger metadata
описывает те же required/optional/nullable/enum/range значения.
Используй типизированные response DTO, ApiOkResponse/другой фактический status
и существующий ApiProblemResponses. Prisma model не является public contract:
response выбирает поля явно. Stable codes, RFC 9457 профиль и mapping принадлежат
Errors.
Безопасный путь: используй exception и общий filter, а не локальный
res.status(...).json(...). Исключение — транспортная операция вроде cookie;
следуй существующему auth controller с passthrough и явно заданным status.
Пример и проверка
Prefix /api/v1 задаёт configureApp. Route/status/request/response/OpenAPI
change — изменение публичного backend contract; несовместимое изменение требует
согласованного перехода consumers, а не незаметной правки DTO. Новый API version
не вводи для внутреннего refactor.
Pagination сохраняет contract endpoint: operations использует opaque cursor, limit и DTO bounds. Не заменяй cursor offset/page и не добавляй global pagination helper ради первого endpoint. Новая pagination явно определяет порядок, границу страницы и end-of-list; reused cursor не должен менять filters/owner.
Operations controller показывает guard, user.sub, DTO query и service delegation. Для нового field обновляй Nest DTO/metadata и публикуемый OpenAPI artifact. Потребители получают публичный контракт независимо от внутреннего устройства API.
Проверь happy path и применимые invalid input/access/not-found/domain/upstream
errors на boundary, где они возникают. Unit вызов controller не запускает pipes,
guards или serialization. npm run test:openapi-contract проверяет schema parity,
но не поведение invalid request; выбирай соответствующий test по
Testing. Финальный gate не заменяет semantic review ошибок.
Источник контракта
Nest DTO/controllers/Swagger metadata определяют публичный HTTP API.
npm run openapi:generate собирает backend и записывает корневой openapi.json.
Nest preview читает metadata без запуска HTTP-порта, провайдеров, БД и T-Bank;
команда не требует deployment environment. Artifact исключён из Git.
При изменении API обнови DTO/metadata и выполни генерацию. Потребители получают
artifact отдельно; backend не читает их репозитории. test:openapi-contract
сравнивает вывод генератора с runtime schema configured app во временном каталоге.
Проверка подтверждает правильность генерации, но без versioned baseline не
выявляет breaking change относительно предыдущего выпуска. Для такого изменения
согласуй переход consumers и проверь relevant HTTP behavior.
HTTP prefix — /api/v1; Swagger доступен согласно src/config/swagger.config.ts.
Общий error response — application/problem+json со status и публичным code.
Validation требует 400 / VALIDATION_ERROR и errors: [{ pointer, detail }].
Известное ограничение: ValidationPipe сейчас формирует строковые сообщения,
а filter ожидает структурированные field errors; schema parity не доказывает
правильность errors. Изменение требует проверки реального HTTP pipeline.