Sergey Krylov a13b5145f7
Some checks failed
CI / ci (pull_request) Failing after 3m32s
CI / ci (push) Failing after 2m50s
docs(frontend): align tooling spec with implementation
2026-06-23 21:30:11 +03:00

118 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Frontend Infrastructure Tooling — Implementation Plan
## Architecture Decisions
### ADR references
- ADR-005: Biome вместо ESLint + Prettier
- ADR-006: TanStack Router вместо react-router-dom
- ADR-007: OpenAPI codegen как единый источник типов
### Non-ADR decisions
- ky как единый HTTP-клиент — выбор библиотеки, не меняющий архитектуры
- MSW browser mode — расширение существующей инфраструктуры тестов
- Zod для env validation — утилитарное улучшение
## Phases
Выполнять последовательно для минимизации конфликтов.
### Phase 1 — ky Migration
*Низкий риск, обратно совместим*
1. Доработать `kyClient.ts`:
- Добавить нормализацию конверта (normalizeEnvelope) в afterResponse hook
- Экспортировать `kyApi` и `configureKyAuth`
2. Поочерёдно перевести entity API на `kyApi`:
- session, stock, bond, search, portfolio, broker-*
3. Удалить `shared/api/client.ts`
4. Заменить `configureAuth``configureKyAuth` в точке входа
5. Прогнать тесты — поведение не должно измениться
### Phase 2 — Biome
*Средний риск — изменения в коде при авто-миграции*
1. Установить `@biomejs/biome`
2. `npx @biomejs/biome migrate eslint --write`
3. Создать `biome.json`, донастроить:
- Отключить несовместимые правила
- Настроить `files.ignore`, `linter.rules`
4. Проверить FSD-правила: @conarti/feature-sliced не портируются в Biome → оставить минимальный `.eslintrc.cjs` только для FSD
5. Удалить `eslint`, `prettier`, `.eslintrc.cjs` (если FSD не нужен)
6. Обновить `package.json`: `lint` скрипт → `biome check`
7. Обновить CI в `.gitea/workflows/ci.yml`
8. Обновить pre-commit hook (lint-staged → biome)
9. Прогнать `biome check --write`, закоммитить
10. Прогнать тесты
### Phase 3 — Unify API Types
*Низкий риск*
> **Фактический подход: ре-экспорты в index.ts вместо types.ts.**
> В процессе реализации выяснилось, что direct-импорты из `types.ts` ведут к многословным `components['schemas']['XxxDto']` в 60+ файлах. Принято решение перенести friendly-name ре-экспорты из `responses.ts` в `index.ts`. Таким образом `responses.ts` удалён, а единая точка входа — `@/shared/api`.
1. Перенести friendly-name type-алиасы из `responses.ts` в `shared/api/index.ts`
2. Удалить `shared/api/responses.ts`
3. Переключить все импорты с `@/shared/api/responses` на `@/shared/api`
4. Перенести normalizeEnvelope (ky-версию) в `shared/api/kyClient.ts`
5. Прогнать `npm run build`
### Phase 4 — MSW Browser
*Низкий риск, handlers готовы*
1. Создать `apps/frontend/mocks/browser.ts` (setupWorker)
2. Прокинуть в `public/mockServiceWorker.js` через `npx msw init public/`
3. Создать `shared/config/env.ts` с чтением `VITE_API_MOCK`
4. Подключить MSW browser в `main.tsx` по условию
5. Проверить `npm run dev VITE_API_MOCK=true` без бэкенда
### Phase 5 — Env Validation
*Низкий риск*
1. Расширить `shared/config/env.ts` — Zod-схема для всех VITE_*
2. Вызвать валидацию в `main.tsx` до рендера
### Phase 6 — TanStack Router
*Крупный, высокий риск*
> **Фактический подход: code-first вместо file-based.**
> В процессе реализации выяснилось, что `@tanstack/router-plugin` не генерирует `routeTree.gen.ts` корректно на данной версии Vite/плагина. Принято решение использовать code-first подход — все маршруты определяются вручную в `routeTree.tsx`.
1. Установить зависимости:
- `@tanstack/react-router`
- `@tanstack/router-devtools` (devDependency)
2. Создать `src/app/routing/routeTree.tsx` — code-first дерево маршрутов:
- Все маршруты определены в одном файле через `createRootRoute`, `createRoute`, `createRouter`
- `beforeLoad` для guard'ов (`requireAuth`)
- Loaders для предзагрузки отложены
3. Создать `src/app/routing/router.ts`:
- `createRouter()` с Route Tree из `routeTree.tsx`
4. Заменить `<BrowserRouter>` + `<Routes>``<RouterProvider>` в `App.tsx`
5. Заменить все импорты `react-router-dom` по всему проекту:
- `Link``Link` из `@tanstack/react-router`
- `useNavigate``useNavigate({ to: '...' })` (объектный синтаксис)
- `useParams``useParams`
- `useSearchParams``useSearchParamsCompat` (временная обёртка, т.к. TanStack Router не экспортирует useSearchParams)
- `useLocation``useLocation`
6. Заменить `MemoryRouter` в тестах на `createMemoryHistory` + `RouterProvider`
7. Обновить `test-utils.tsx` — рендер-обёртка на TanStack Router
8. Настроить router-devtools в dev-режиме
9. Прогнать тесты, проверить сборку
## Dependencies
```
Phase 1 (ky) → независим
Phase 2 (Biome) → независим
Phase 3 (Types) → после Phase 1 (ky меняет нормализацию)
Phase 4 (MSW) → после Phase 5 (env нужен для VITE_API_MOCK)
Phase 5 (Env) → независим
Phase 6 (Router) → после Phase 3 (типы API стабильны)
```
## Rollback Strategy
- Каждый phase — отдельный коммит, можно revert по одному
- Biome: `.eslintrc.cjs` сохраняется как `.eslintrc.cjs.bak` до верификации
- Router: старый `AppRoutes.tsx` и `react-router-dom` не удаляются до полного прохождения тестов
- Каждый phase должен оставлять `npm run build` и `npm run test` зелёными