Mark completed tasks across all 6 phases, document code-first router approach deviation, update Phase 6 plan with actual steps
114 lines
6.0 KiB
Markdown
114 lines
6.0 KiB
Markdown
# 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
|
||
*Низкий риск*
|
||
|
||
1. Убедиться, что все entity API импортируют из `types.ts` (codegen)
|
||
2. Удалить `shared/api/responses.ts`
|
||
3. Перенести normalizeEnvelope (ky-версию) в `shared/api/kyClient.ts`
|
||
4. Прогнать `npm run build`
|
||
|
||
### Phase 4 — MSW Browser
|
||
*Низкий риск, handlers готовы*
|
||
|
||
1. Создать `shared/lib/test/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` зелёными
|