# Frontend FSD Shared Layer Дата: 2026-06-20 Статус: спецификация ## Контекст Broker FSD pilot завершён: broker-домен работает в FSD-слоях entities/widgets/pages. Следующий шаг миграции — нормализация shared-инфраструктуры. Сейчас общий код размазан по техническим каталогам (`api/`, `components/`, `context/`, `hooks/`), и FSD-сущности вынуждены импортировать из них через длинные относительные пути (`../../../api/client`). Это мешает введению import boundaries и усложняет дальнейшую миграцию доменов. ## Цель Создать FSD-слой `shared/` с явным public API, в который переносится truly shared инфраструктурный код: базовый HTTP-клиент, типы ответов API, переиспользуемые UI-примитивы без доменной логики. ## Область изменений ### Входит - Перенос `api/client.ts`, `api/responses.ts`, `api/types.ts` в `shared/api/` - Перенос компонентов без доменных зависимостей (`SkeletonBlock`, `TableSkeleton`) в `shared/ui/` - Превращение исходных файлов в re-export shims (стратегия coexistence, как в broker pilot) - Переключение импортов в FSD-сущностях и legacy hooks на `@/shared/api/...` ### Не входит - Layout и ProtectedRoute — остаются в `components/` (зависят от доменного кода SearchBar, useAuth) - SearchBar, StockDetails, BondDetails, PriceChart — доменные компоненты, остаются на месте - AuthContext — остаётся в `context/` (будет перенесён при миграции auth-домена или app-слоя) - Все доменные API-функции (`getShare`, `getBond`, `searchSecurities` и т.д.) — остаются в `api/client.ts` как есть, будут вынесены при миграции соответствующих доменов - Все доменные типы (`ShareResponse`, `Portfolio`, `ScreenerItem` и т.д.) — остаются в `api/responses.ts` как есть - Import guards, ESLint boundaries — отложены до стабилизации слоёв ## Требования ### 1. shared/api/ содержит базовую HTTP-инфраструктуру `shared/api/client.ts` включает: - Базовый HTTP-клиент (`request`, `setAccessToken`, `getAccessToken`, `setOnUnauthorized`) - Все доменные API-функции (как временная мера до миграции доменов) `shared/api/responses.ts` включает все типы ответов API (как временная мера). `shared/api/types.ts` — generated OpenAPI types. ### 2. shared/ui/ содержит только truly generic UI-компоненты В `shared/ui/` попадают только компоненты без импортов доменного кода: - `SkeletonBlock` — примитивный скелетон (нет зависимостей) - `TableSkeleton` — табличный скелетон (зависит только от SkeletonBlock) Layout и ProtectedRoute остаются в legacy `components/`, так как импортируют SearchBar и useAuth. ### 3. Coexistence через shims Исходные файлы в `api/` и `components/` превращаются в re-export shims. ### 4. FSD-сущности импортируют через @/shared/ Импорты в entities/widgets/pages меняются с относительных на `@/shared/api/...`. ## Acceptance Criteria - `src/shared/api/client.ts`, `responses.ts`, `types.ts` существуют и экспортируют всё, что экспортировали исходные файлы - `src/shared/ui/SkeletonBlock.tsx` и `src/shared/ui/TableSkeleton.tsx` существуют - Исходные файлы `api/client.ts`, `api/responses.ts`, `api/types.ts` стали re-export shims - Исходные файлы `components/SkeletonBlock.tsx`, `components/TableSkeleton.tsx` стали re-export shims - Все FSD entity импорты `../../../api/...` заменены на `@/shared/api/...` - Все legacy hooks используют `@/shared/api/...` вместо `../api/...` - `npm test -w apps/frontend` — PASS - `npm run lint -w apps/frontend` — PASS - `npm run build -w apps/frontend` — PASS ## Ограничения - Никаких изменений поведения UI - Не меняется структура ответов API - Layout, ProtectedRoute, AuthContext остаются на месте - Не затрагиваются backend, docs, CI