docs: update tasks and plan to reflect actual implementation progress

Mark completed tasks across all 6 phases, document code-first
router approach deviation, update Phase 6 plan with actual steps
This commit is contained in:
Sergey Krylov 2026-06-23 06:54:29 +03:00
parent cfadb2adbe
commit 7e10b4b8aa
2 changed files with 88 additions and 105 deletions

View File

@ -70,48 +70,29 @@
### Phase 6 — TanStack Router ### Phase 6 — TanStack Router
*Крупный, высокий риск* *Крупный, высокий риск*
> **Фактический подход: code-first вместо file-based.**
> В процессе реализации выяснилось, что `@tanstack/router-plugin` не генерирует `routeTree.gen.ts` корректно на данной версии Vite/плагина. Принято решение использовать code-first подход — все маршруты определяются вручную в `routeTree.tsx`.
1. Установить зависимости: 1. Установить зависимости:
- `@tanstack/react-router` - `@tanstack/react-router`
- `@tanstack/router-devtools` (devDependency) - `@tanstack/router-devtools` (devDependency)
- `@tanstack/router-plugin` (vite plugin) 2. Создать `src/app/routing/routeTree.tsx` — code-first дерево маршрутов:
2. Настроить Vite plugin в `vite.config.ts` - Все маршруты определены в одном файле через `createRootRoute`, `createRoute`, `createRouter`
3. Создать файловую структуру роутов: - `beforeLoad` для guard'ов (`requireAuth`)
``` - Loaders для предзагрузки отложены
src/app/routes/ 3. Создать `src/app/routing/router.ts`:
__root.tsx — AppLayout + ErrorBoundary - `createRouter()` с Route Tree из `routeTree.tsx`
index.tsx — HomePage 4. Заменить `<BrowserRouter>` + `<Routes>``<RouterProvider>` в `App.tsx`
stocks.$secid.tsx — StockPage 5. Заменить все импорты `react-router-dom` по всему проекту:
bonds.$secid.tsx — BondPage
screener.tsx — ScreenerPage + Zod search params
login.tsx — LoginPage
register.tsx — RegisterPage
profile.tsx — ProfilePage (guard: beforeLoad)
portfolios.tsx — PortfoliosListPage (guard)
portfolios.$id.tsx — PortfolioDetailPage (guard)
broker/
index.tsx — BrokerAccountsPage (guard)
$accountId/
index.tsx — BrokerAccountOverviewPage (guard)
shares.tsx — BrokerPositionsPage (guard)
bonds.tsx — BrokerPositionsPage (guard)
operations.tsx — BrokerOperationsPage + Zod search params (guard)
events.tsx — BrokerEventsPage (guard)
```
4. Перенести каждый роут из `AppRoutes.tsx` — каждый файл создаёт lazy route
5. Создать роутер в `app/routing/router.ts`:
- `createRouter()` с Route Tree
- `beforeLoad` для guard'ов
- Loaders для предзагрузки (TanStack Query integration)
6. Заменить `<BrowserRouter>` + `<Routes>``<RouterProvider>` в `App.tsx`
7. Заменить все импорты `react-router-dom` по всему проекту:
- `Link``Link` из `@tanstack/react-router` - `Link``Link` из `@tanstack/react-router`
- `useNavigate``useNavigate` - `useNavigate``useNavigate({ to: '...' })` (объектный синтаксис)
- `useParams``useParams` - `useParams``useParams`
- `useSearchParams``useSearch` + `useNavigate` - `useSearchParams``useSearchParamsCompat` (временная обёртка, т.к. TanStack Router не экспортирует useSearchParams)
- `useLocation``useLocation` - `useLocation``useLocation`
8. Заменить `MemoryRouter` в тестах на `createMemoryRouter` из TanStack Router 6. Заменить `MemoryRouter` в тестах на `createMemoryHistory` + `RouterProvider`
9. Настроить router-devtools в dev-режиме 7. Обновить `test-utils.tsx` — рендер-обёртка на TanStack Router
10. Прогнать тесты 8. Настроить router-devtools в dev-режиме
9. Прогнать тесты, проверить сборку
## Dependencies ## Dependencies

View File

@ -2,104 +2,106 @@
## Phase 1: ky Migration ## Phase 1: ky Migration
- [ ] Доработать `shared/api/kyClient.ts`: добавить normalizeEnvelope в afterResponse hook - [x] Доработать `shared/api/kyClient.ts`: добавить normalizeEnvelope, request, kyApi, configureKyAuth
- [ ] Экспортировать `kyApi` (create экземпляр) и `configureKyAuth` из kyClient - [x] Экспортировать `kyApi` (create экземпляр) и `configureKyAuth` из kyClient
- [ ] Перевести `entities/session/api/sessionApi.ts` на kyApi - [x] Перевести `entities/session/api/sessionApi.ts` на kyApi
- [ ] Перевести `entities/stock/api/stockApi.ts` на kyApi - [x] Перевести `entities/stock/api/stockApi.ts` на kyApi
- [ ] Перевести `entities/bond/api/bondApi.ts` на kyApi - [x] Перевести `entities/bond/api/bondApi.ts` на kyApi
- [ ] Перевести `entities/search/api/searchApi.ts` на kyApi - [x] Перевести `entities/search/api/searchApi.ts` на kyApi
- [ ] Перевести `entities/portfolio/api/portfolioApi.ts` на kyApi - [x] Перевести `entities/portfolio/api/portfolioApi.ts` на kyApi
- [ ] Перевести `entities/broker-account/api/brokerAccountApi.ts` на kyApi - [x] Перевести `entities/broker-account/api/brokerAccountApi.ts` на kyApi
- [ ] Перевести `entities/broker-position/api/brokerPositionApi.ts` на kyApi - [x] Перевести `entities/broker-position/api/brokerPositionApi.ts` на kyApi
- [ ] Перевести `entities/broker-operation/api/brokerOperationApi.ts` на kyApi - [x] Перевести `entities/broker-operation/api/brokerOperationApi.ts` на kyApi
- [ ] Перевести `entities/broker-event/api/brokerEventApi.ts` на kyApi - [x] Перевести `entities/broker-event/api/brokerEventApi.ts` на kyApi
- [ ] Перевести `features/screener/api/screenerApi.ts` на kyApi - [x] Перевести `features/screener/api/screenerApi.ts` на kyApi
- [ ] Удалить `shared/api/client.ts` - [x] Удалить `shared/api/client.ts`
- [ ] Заменить `configureAuth()` на `configureKyAuth()` в точке входа (AppProviders) - [x] Заменить `configureAuth()` на `configureKyAuth()` в SessionProvider
- [ ] `npm run test` — все тесты проходят - [x] `npm run test` — все тесты проходят
- [ ] `npm run build` — сборка проходит - [x] `npm run build` — сборка проходит
## Phase 2: Biome Migration ## Phase 2: Biome Migration
- [ ] Research: проверить Biome plugin system на поддержку FSD/import-no-restricted-paths - [ ] Research: проверить Biome plugin system на поддержку FSD/import-no-restricted-paths
- [ ] Установить `@biomejs/biome` (devDependency) - [x] Установить `@biomejs/biome` (devDependency)
- [ ] Запустить `npx @biomejs/biome migrate eslint --write` - [ ] Запустить `npx @biomejs/biome migrate eslint --write`
- [ ] Создать `biome.json` с донастройкой под проект - [x] Создать и настроить `biome.json` под проект
- [ ] Если FSD-правила не портируются — создать минимальный `.eslintrc.cjs` только для FSD - [x] ESLint оставлен только для FSD-правил (`.eslintrc.cjs`)
- [ ] Удалить зависимости: eslint, prettier, @typescript-eslint/*, eslint-plugin-* - [ ] Удалить зависимости: prettier, @typescript-eslint/*, eslint-plugin-* (ESLint core пока нужен для FSD)
- [ ] Удалить `.eslintrc.cjs` (если FSD не нужен) - [ ] Удалить `.prettierrc` и `.prettierignore` — форматирование перешло к Biome
- [ ] Обновить `package.json`: `lint``biome check src/` - [x] Обновить `package.json`: `lint``biome check src/`
- [ ] Обновить `.gitea/workflows/ci.yml`: заменить eslint на biome - [ ] Обновить `.gitea/workflows/ci.yml`: заменить eslint на biome для frontend
- [ ] Обновить pre-commit hook (lint-staged → biome) - [x] Обновить pre-commit hook (lint-staged → biome + prettier)
- [ ] Прогнать `biome check --write src/` - [x] Прогнать `biome check --write src/`
- [ ] `npm run test` — все тесты проходят - [x] `npm run test` — все тесты проходят
- [x] `npm run build` — сборка проходит
## Phase 3: Unify API Types ## Phase 3: Unify API Types
- [ ] Проверить все импорты в entity API — должны быть из `types.ts` (codegen), не из `responses.ts` - [ ] Аудит импортов: entity API используют `types.ts` (codegen) или `responses.ts`?
- [ ] Если кто-то импортирует из `responses.ts` — переключить на `types.ts` - [ ] Переключить все импорты с `responses.ts` на `types.ts` (если типы есть в codegen)
- [ ] Удалить `shared/api/responses.ts` - [ ] Удалить `shared/api/responses.ts` (после переключения)
- [ ] Перенести normalizeEnvelope (ky-версия) в `shared/api/kyClient.ts` - [x] normalizeEnvelope перенесён в `shared/api/kyClient.ts`
- [ ] `npm run build` — сборка проходит - [ ] `npm run build` — сборка проходит
## Phase 4: MSW Browser ## Phase 4: MSW Browser
- [ ] Создать `shared/lib/test/browser.ts` (setupWorker из msw/browser) - [x] Создать `shared/lib/test/browser.ts` (setupWorker из msw/browser)
- [ ] Установить и прокинуть mockServiceWorker.js: `npx msw init public/` - [x] Установить и прокинуть mockServiceWorker.js: `npx msw init public/`
- [ ] Создать `shared/config/env.ts` с чтением и экспортом VITE_API_MOCK - [x] Создать `shared/config/env.ts` с чтением и экспортом VITE_API_MOCK + VITE_API_URL
- [ ] В `main.tsx`: при `VITE_API_MOCK === 'true'` запускать `worker.start()` - [x] В `main.tsx`: при `VITE_API_MOCK === 'true'` запускать `worker.start()`
- [ ] Проверить: `VITE_API_MOCK=true npm run dev` без бэкенда — приложение работает - [ ] Проверить: `VITE_API_MOCK=true npm run dev` без бэкенда — приложение работает
- [ ] Проверить: `VITE_API_MOCK=false npm run dev` — запросы идут на бэкенд - [ ] Проверить: `VITE_API_MOCK=false npm run dev` — запросы идут на бэкенд
## Phase 5: Env Validation ## Phase 5: Env Validation
- [ ] Разработать Zod-схему в `shared/config/env.ts` для всех VITE_* переменных - [x] Разработать Zod-схему в `shared/config/env.ts` для всех VITE_* переменных
- [ ] Вызвать `validateEnv()` в `main.tsx` до `ReactDOM.createRoot` - [x] Валидация env выполняется при импорте (safeParse в модуле env.ts)
- [ ] Проверить: при отсутствии обязательной переменной — понятная ошибка - [ ] Проверить: при отсутствии обязательной переменной — понятная ошибка
## Phase 6: TanStack Router ## Phase 6: TanStack Router
### Setup ### Setup
- [ ] Установить `@tanstack/react-router`, `@tanstack/router-devtools`, `@tanstack/router-plugin` - [x] Установить `@tanstack/react-router`, `@tanstack/router-devtools`
- [ ] Настроить Vite plugin для генерации RouteTree в `vite.config.ts` - [ ] ~~Установить `@tanstack/router-plugin`~~ (решение: code-first, без плагина)
### Route files ### Route files
- [ ] Создать `src/app/routes/__root.tsx` — AppLayout + ErrorBoundary - [x] Создать `src/app/routing/routeTree.tsx` — все маршруты (code-first)
- [ ] Создать `src/app/routes/index.tsx` — HomePage - [x] root route + AppLayout
- [ ] Создать `src/app/routes/stocks.$secid.tsx` — StockPage - [x] index → HomePage
- [ ] Создать `src/app/routes/bonds.$secid.tsx` — BondPage - [x] stocks/$secid → StockPage
- [ ] Создать `src/app/routes/screener.tsx` — ScreenerPage + Zod search params - [x] bonds/$secid → BondPage
- [ ] Создать `src/app/routes/login.tsx` — LoginPage - [x] screener → ScreenerPage
- [ ] Создать `src/app/routes/register.tsx` — RegisterPage - [x] login → LoginPage
- [ ] Создать `src/app/routes/profile.tsx` — ProfilePage (guard: beforeLoad) - [x] register → RegisterPage
- [ ] Создать `src/app/routes/portfolios.tsx` — PortfoliosListPage (guard) - [x] profile → ProfilePage (guard)
- [ ] Создать `src/app/routes/portfolios.$id.tsx` — PortfolioDetailPage (guard) - [x] portfolios → PortfoliosListPage (guard)
- [ ] Создать `src/app/routes/broker/index.tsx` — BrokerAccountsPage (guard) - [x] portfolios/$id → PortfolioDetailPage (guard)
- [ ] Создать `src/app/routes/broker.$accountId/index.tsx` — BrokerAccountOverviewPage (guard) - [x] broker → BrokerAccountsPage (guard)
- [ ] Создать `src/app/routes/broker.$accountId/shares.tsx` — BrokerPositionsPage (guard) - [x] broker/$accountId → BrokerAccountOverviewPage (guard)
- [ ] Создать `src/app/routes/broker.$accountId/bonds.tsx` — BrokerPositionsPage (guard) - [x] broker/$accountId/shares → BrokerPositionsPage (guard)
- [ ] Создать `src/app/routes/broker.$accountId/operations.tsx` — BrokerOperationsPage (guard) - [x] broker/$accountId/bonds → BrokerPositionsPage (guard)
- [ ] Создать `src/app/routes/broker.$accountId/events.tsx` — BrokerEventsPage (guard) - [x] broker/$accountId/operations → BrokerOperationsPage (guard)
- [x] broker/$accountId/events → BrokerEventsPage (guard)
### Router integration ### Router integration
- [ ] Создать `app/routing/router.ts`: `createRouter()` с Route Tree - [x] Создать `app/routing/router.ts`: `createRouter()` с Route Tree
- [ ] Настроить `beforeLoad` для guard'ов - [x] Настроить `beforeLoad` для guard'ов (requireAuth)
- [ ] Настроить loaders для предзагрузки (TanStack Query) - [ ] Настроить loaders для предзагрузки (TanStack Query) — отложено
- [ ] Заменить `<BrowserRouter>` + `<Routes>``<RouterProvider>` в `App.tsx` - [x] Заменить `<BrowserRouter>` + `<Routes>``<RouterProvider>` в `App.tsx`
### Replace imports ### Replace imports
- [ ] Заменить `Link``@tanstack/react-router` Link по всему проекту - [x] Заменить `Link``@tanstack/react-router` Link по всему проекту
- [ ] Заменить `useNavigate``@tanstack/react-router` - [x] Заменить `useNavigate``@tanstack/react-router`
- [ ] Заменить `useParams``@tanstack/react-router` - [x] Заменить `useParams``@tanstack/react-router`
- [ ] Заменить `useSearchParams``useSearch` + `useNavigate` - [x] Заменить `useSearchParams``useSearchParamsCompat` (временная обёртка)
- [ ] Заменить `useLocation``@tanstack/react-router` - [x] Заменить `useLocation``@tanstack/react-router`
### Tests ### Tests
- [ ] Заменить `MemoryRouter` в тестах на `createMemoryRouter` из TanStack Router - [x] Заменить `MemoryRouter` в тестах на `createMemoryHistory` + `RouterProvider`
- [ ] Обновить тестовые утилиты (`test-utils.tsx`) - [x] Обновить тестовые утилиты (`test-utils.tsx`)
- [ ] `npm run test` — все тесты проходят - [x] `npm run test` — все тесты проходят (125)
- [ ] `npm run build` — сборка проходит - [x] `npm run build` — сборка проходит
### Devtools ### Devtools
- [ ] Настроить `@tanstack/router-devtools` в dev-режиме - [x] Настроить `@tanstack/router-devtools` в dev-режиме
- [ ] Проверить навигацию по всем страницам вручную - [ ] Проверить навигацию по всем страницам вручную — отложено