docs: simplify conventions layout
Frontend security / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 3m53s
Conventional commits / commits (pull_request) Successful in 19s
Frontend security / security (push) Successful in 8s
Frontend verify / verify (push) Successful in 3m53s
Frontend security / security (pull_request) Successful in 8s
Frontend verify / verify (pull_request) Successful in 3m53s
Conventional commits / commits (pull_request) Successful in 19s
Frontend security / security (push) Successful in 8s
Frontend verify / verify (push) Successful in 3m53s
This commit was merged in pull request #14.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# Frontend data
|
||||
|
||||
## Выбор owner
|
||||
|
||||
Server state принадлежит TanStack Query, form state — React Hook Form, локальное
|
||||
UI — React state. Не копируй успешный query result в useState/context для второго
|
||||
кэша. Domain-specific queries, keys и policies принадлежат вызывающему slice;
|
||||
общий transport — `shared/api`. Page VM выбирает inputs и собирает presentation data.
|
||||
|
||||
Используй `apiClient`/`apiQueryClient` из shared public API. Прямой fetch в
|
||||
pages/features/entities и прямой T-Bank call запрещены. Сначала найди
|
||||
существующий query того же endpoint; расширяй его owner, не создавай второй key
|
||||
или глобальную query policy для одной страницы.
|
||||
|
||||
## Типы и contract
|
||||
|
||||
Backend-owned OpenAPI contract поступает во frontend как предоставленный
|
||||
актуальный snapshot; generated `schema.d.ts` производен от него. Тип
|
||||
request/response бери из generated `paths`, например:
|
||||
|
||||
```ts
|
||||
type User = paths["/api/v1/auth/me"]["get"]["responses"][200]["content"]["application/json"];
|
||||
```
|
||||
|
||||
Domain/UI type допустим, когда он отличается по смыслу, а не копирует transport DTO.
|
||||
Generated TS вручную не исправляется. Не добавляй параллельный fetch/axios
|
||||
client, runtime schema, hash/checksum registry или дополнительный drift checker
|
||||
без отдельной текущей потребности; existing OpenAPI flow уже владеет генерацией. Frontend-команды не читают соседний
|
||||
backend checkout и не проверяют backend runtime OpenAPI; изменение wire
|
||||
shape/status/route сохраняет
|
||||
[границу HTTP-контракта](../../../docs/architecture/http-api.md#источник-контракта).
|
||||
Одна UI-модель не требует менять API. `openapi:generate` работает offline от snapshot;
|
||||
`openapi:check` генерирует во временный каталог и сравнивает, не меняя tracked files.
|
||||
|
||||
## Auth и invalidation
|
||||
|
||||
Bearer header принадлежит shared authenticated fetch; query/mutation не задают
|
||||
Authorization. Auth endpoints исключены из Bearer/retry middleware. Refresh
|
||||
координируется single-flight; после `401` с `UNAUTHORIZED` возможен один retry.
|
||||
Не добавляй собственный refresh/retry loop в caller.
|
||||
|
||||
Protected queries используют existing session-aware boundary; logout очищает
|
||||
session-scoped cache. При auth/token change читай [security](../../../backend/.ai/conventions/security-auth.md)
|
||||
и [authentication](../../../docs/domains/authentication/overview.md).
|
||||
Успешная connection mutation коммитит подтверждённый status и сбрасывает financial
|
||||
GET subtree; ошибка mutation не меняет generation/cache. Это отдельная граница
|
||||
от обычного фонового refetch: [connection policy](../../../docs/integrations/tbank.md#граница-финансового-кэша).
|
||||
|
||||
Mutations используют существующий generated client и query-key owner;
|
||||
после успеха обновляй/invalidируй только связанные данные. Optimistic update
|
||||
нужен конкретному UX и обязан иметь rollback/error behavior.
|
||||
|
||||
Default focus refetch выключен; freshness и retry определяются существующей
|
||||
[query policy](../../../docs/adr/007-react-query-fetch-policy.md) и feature source.
|
||||
При обычном refetch сохраняй Client Cached Snapshot, при session/connection
|
||||
смене не показывай данные прежнего владельца. UI presentation — в UI convention.
|
||||
|
||||
## Errors
|
||||
|
||||
Извлекай code через existing `apiErrorCode` из shared/api. Backend Problem
|
||||
Details code задаёт machine behavior; user-facing текст принадлежит i18n.
|
||||
Network/unknown error получает безопасное локальное сообщение и retry,
|
||||
не raw exception text. Input/domain failure сохраняет ввод и показывает
|
||||
ошибку у ответственного form/section owner; не маскируй её успешным результатом.
|
||||
|
||||
Если одна группа API codes требует одинакового recovery в нескольких views,
|
||||
сведи классификацию у ближайшего общего owner. Не размножай magic comparisons
|
||||
и не объявляй закрытый frontend error enum: generated `code` пока `string`.
|
||||
Неизвестный новый code должен сохранять fallback. Рефакторинг существующих
|
||||
разных recovery paths требует behavior proof, а не общей обработки всех ошибок.
|
||||
|
||||
## Примеры и проверка
|
||||
|
||||
[usePortfolio](../../src/entities/portfolio/api/usePortfolio.ts) — entity query;
|
||||
[shared client](../../src/shared/api/client.ts) — transport/auth boundary.
|
||||
Изменяя header/retry/invalidation, проверяй наблюдаемое поведение через MSW и
|
||||
[Testing](testing.md); не обращайся к реальному T-Bank.
|
||||
`npm run openapi:check`, `npm run typecheck` и targeted tests проверяют разные
|
||||
части решения. Для API semantics нужны exact docs и проверки наблюдаемого
|
||||
HTTP-поведения на стороне backend.
|
||||
Reference in New Issue
Block a user