# 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. Создать `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. Заменить `` + `` → `` в `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` зелёными