реклама
Бургер менюБургер меню

Юрий Белк – Full stack Developer (страница 4)

18

– turbo решает, что можно выполнить параллельно, а что нужно последовательно.

Например, логика может быть такая:

– сначала генерируем типы из OpenAPI в packages/shared-contract,

– потом бэкенды используют эти артефакты,

– потом фронт использует клиент.

Даже если вы не используете сложные графы задач – turbo всё равно упрощает запуск “всего репо”.

2.3. Общие правила репозитория

Чтобы репо не превратилось в свалку:

1) Все внешние сервисы (Postgres/Redis и т.п.) – в /infra и docker-compose.

2) Контракт API – в одном месте (/packages/shared-contract).

3) Каждый backend должен:

– подниматься командой dev,

– отдавать OpenAPI (если фреймворк умеет),

– запускать миграции отдельной командой.

4) E2E тесты не знают, какой язык под капотом – им важен URL и контракт.

Контракт как основа: OpenAPI-first

Самая важная идея книги: контракт важнее реализации.

Мы будем строить систему так, будто бэкенд – это “плагин”. Сегодня он на NestJS, завтра на FastAPI, послезавтра на Go. Если контракт не меняется – фронт и интеграции не должны страдать.

0.3.1. Что значит OpenAPI-first

OpenAPI-first означает:

1) Сначала описываем API в openapi.yaml.

2) На основе контракта:

– генерируем клиент для фронта,

– генерируем типы/DTO (где это уместно),

– валидируем, что запросы/ответы соответствуют схеме.

3) Реализации бэкенда обязаны соответствовать контракту.

Это дисциплина, которая резко снижает хаос:

– меньше “а давай добавим поле, а фронт потом как-нибудь догадается”,

– меньше разночтений между командами,

– проще писать e2e‑тесты.

Где лежит контракт и как он выглядит

Контракт кладём в:

– /packages/shared-contract/openapi.yaml

Внутри openapi.yaml мы описываем:

– базовую информацию (title, version),

– серверы (на локалке),

– пути (/health, /users, …),

– схемы данных (DTO),

– ошибки (единый формат).

Даже если в каждом бэкенде есть автогенерация OpenAPI (NestJS Swagger, FastAPI docs, Springdoc) – источником истины остаётся наш openapi.yaml.

Автогенерация полезна, но она часто:

– зависит от аннотаций и кода,

– по-разному описывает типы,

– может “уплывать” при рефакторингах.

В книге мы будем делать наоборот: код подстраивается под контракт.

Генерация клиентов и типов

Зачем это нужно:

– фронту нужны типы запросов/ответов,

– e2e‑тестам нужны типы,

– иногда удобно генерировать серверные интерфейсы/заготовки.

Что можно генерировать:

– TypeScript клиент (например, fetch‑клиент или axios‑клиент),

– TypeScript типы DTO,

– (опционально) клиенты для других языков.

В рамках книги важно не то, какой именно генератор вы выберете, а сам принцип:

– контракт обновили → артефакты пересобрали → всё компилируется/тестируется.

Хорошая практика: хранить сгенерированный код либо:

– в packages/shared-contract/dist (и не коммитить, генерировать в CI), либо

– коммитить в репозиторий (проще для новичков, меньше магии).

Для учебной книги часто удобнее второй вариант (видно, что получилось). Для промышленной разработки обычно выбирают первый (генерация в CI).

Валидация контракта в CI

Контракт должен проверяться автоматически, иначе он быстро перестанет быть “истиной”.

Минимальный набор проверок:

1) Линт OpenAPI – формат, обязательные поля, правила стиля.

2) Валидация схемы – файл реально соответствует OpenAPI версии 3.x.