- fix(backend): case-insensitive unique email, revoke PUBLIC schema access, pin Argon2id params - test(backend): assert password length cap boundary (256 ok, 257 rejected) - docs(backend): plan — typed JWT token kinds so refresh/device tokens cannot pass as access tokens - feat(backend): JWT access/refresh token issue and verify - feat(backend): accounts repository (create/find_by_email/find_by_id) - refactor(gui): LoVisualAddonManagerScreen 989→10 файлов addon/ (8.5.2) - docs(backend): plan — fix sqlx::migrate! path in integration tests - feat(backend): POST /auth/register and /auth/login - refactor(settings): SettingsPanelComponent 715→81 + 6 helpers (8.5.2) - docs(backend): plan — harden device flow (single-use codes, bounded store, 404/429) - feat(backend): OAuth device authorization grant for mod login - fix(backend): first confirm wins for device codes - docs(backend): plan — split Task 8 (refactor) and Task 9 (avatars), harden avatar handling - refactor(mixins): LocalPlayerMixin 691→111 + 4 handlers (8.5.2) - refactor(visuals): Trails 687→130 (8.5.2) - refactor(render): ItemBatchRenderer 677->100 (8.5.2) - refactor(visuals): ReimaginedVisual 674→118 + 5 helpers (8.5.2) - refactor(config): ConfigSerializer 668→91 + 4 helpers (8.5.2) - refactor(hud): DynamicIsland 661→158 + 4 helpers (8.5.2) - refactor(render): GlStencilFramebufferSupport 666→169 (8.5.2) - refactor(gui): MenuScreen 669→128 + 4 helpers (8.5.2) - refactor(render): UiStyle 644→170 + 3 helpers (8.5.2) - refactor(gui): ModuleComponent 613→98 + 4 helpers (8.5.2) - refactor(media): MediaSessionService 616→200 + 4 helpers (8.5.2) - refactor(gui): RelationsComponent 661→59 + 4 helpers (8.5.2) - chore(license): strip GPL file headers from all Java sources - refactor(aiming): PointTracker 583→168 + 2 helpers (8.5.2) - refactor(gui): LoVisualProxyManagerScreen 591→132 + 2 helpers (8.5.2) - refactor(visuals): KillEffect 588→96 + 4 helpers (8.5.2) - refactor(render): MeshBuilder +4 helpers (8.5.2) - refactor(visuals): extract WorldParticlesRender helper (8.5.2) - refactor(world): ExplosionDamageUtil 551→116 + 2 helpers (8.5.2) - refactor(visuals): TazikHat 596->179 + Model + Palette in hats/tazik (8.5.2) - chore(license): strip GPL header from remaining 30 files and make strip script variant-aware - refactor(gui): ThemeComponent 561->166 + CardRenderer + ScrollState (8.5.2) - refactor(hud): CustomHotbar 556→178 + Renderer + Selection + SelectionGradient (8.5.2) - refactor(gui): ThemeCardRenderer perf + readability polish - refactor(clickgui): CooldownRulesSetting 596->198 + Editor + DetailRenderer (8.5.2) - refactor(hud): HudNotifier 561->200 + Painter + runtime/HudNotifierRuntime (8.5.2) - refactor(theme): Themes 555->168 + impl/Transition + impl/Blending + impl/ProfileCodec (8.5.2) - refactor(theme): EditableClickGuiTheme 205->185 + JavaDoc (8.5.2) - refactor(theme): ThemeStore 491->128 + store/ThemeStoreJson + store/ThemeStoreIO (8.5.2) - refactor(clickgui): ClickGuiRenderer 604->200 compacted one-line delegators + JavaDoc (8.5.2) - refactor(mainmenu): LoVisualMainMenuScreen 551->161 + impl/Painter + impl/Renderer + impl/TextUtil (8.5.2) - refactor(clickgui): ClickGuiTextEditorState 531->187 + impl/EditorCaret + impl/EditorPainter (8.5.2) - refactor(tab): TabListModel 525->139 + model/Collector + model/Reader + model/Signature + model/TextSplitter (8.5.2) - refactor(backend): shared bearer helper and test helpers, build_app takes Config, validate JWT secret strength - refactor(module): ModuleManager 521->198 + impl/Registrar + impl/Dispatcher (8.5.2) - feat(backend): avatar upload with decode, square crop, PNG re-encode and S3 storage - refactor(clip): ClipFunction 512->146 + impl/Geometry + impl/Debug (8.5.2) - docs(backend): implementation plans for gateway (auth hardening, gRPC, rate limits) and configs-service - refactor(iris-patch): ShaderPatchEngine 499->146 + impl/Repo (8.5.2) - chore(frontend): add router, react-query, fonts and vitest; dev proxy to gateway - refactor(hud): ScriptedListHudPanel 499->158 + panel/Props + panel/Signature (8.5.2) - refactor(hud): BaseHudElement 499->199 + impl/Registry + impl/Namer + impl/Prewarm (8.5.2) - refactor(clickgui): Setting 498->170 + impl/Localization + impl/I18n (8.5.2) - refact(viewmodel): split swing animations into camera/swing package - refact(kineticlyrics): split module into stage, playback and modes - rename(holeesp): module HoleESP -> CrystalHoles - refact(crystalholes): split module into crystal scanner, renderer and safety - refact(addonmanager): split manager into lifecycle, runtime, descriptors and profiles - refact(accountconfig): split config into store, session and value helpers - refactor(render): CustomTextRenderer 229->195, extract glyph-pass into GradientTexts helper - docs(TODO): mark AddonManager split done; close 9.2 refactor gate - refactor(media): LinuxMediaSession 441->148, split reader + track/seek state - refactor(nametags): split NameTags into facade + impl helpers - refactor(clickgui): split MainSettingsComponent into facade + scroll + model - refactor(hud): split CustomBar into facade, model and BarSettings - docs(frontend): implementation plan with design system from the mod theme - feat(frontend): design tokens from the mod theme, fonts and shared UI kit - fix(accounts): run migrations on startup, offload Argon2, validate register input, JSON error shape - docs(gateway): plan note on splitting auth handlers before refresh endpoints - feat(frontend): API client with silent refresh, error descriptions and test helpers - style(mod): group compact one-line bulk query methods in ModuleManager - feat(frontend): session restore, login and registration with client-side validation - refactor(hud): split CustomHealthBar into facade + painter + script renderer - docs(mod): record the 2026-09-24 HUD/settings split wave in TODO phase 8.5 - refactor(rhi): split GlStencilShapeClipBackend into facade + native-state + pass-lifecycle helpers - refactor(rhi): split VulkanRenderStateBridge into facade + MSAA and stencil state helpers - refactor(backtrack): split BacktrackController into facade + model + impl helpers - refactor(svg): split SvgPathParser into facade + arc geometry + command/curve helpers - refactor(mixin): split ClientPacketListenerMixin into hook-only mixin + handlers - refactor(renderer3d): un-nest batch bindings + culling into sibling impl types - refactor(renderwarp): extract static factories + geometry into impl helpers - feat(backend): add common crate with shared JWT, internal gateway contract and accounts proto - refactor(guimixin): move hook bodies into handlers, keep mixin as hooks + shadows - feat(accounts): accept only gateway traffic, read identity from gateway header - refactor(cacheduiscriptruntime): extract engine, hashing and frame stats into impl - refactor(customskyboxrenderer): extract projection, shader passes and sun into impl - refactor(betterchatstoremanager): extract persistence, key/path and hover helpers into impl - feat(accounts): rotating opaque refresh tokens in httpOnly cookie, /auth/refresh and /auth/logout - refactor(targetesp): extract crystal rendering subsystem into impl/TargetEspCrystalRenderer - refactor(betterchathovercache): extract disk codec and lookup indexing into impl/ChatHoverCacheCodec - refactor(microsoftauth): split HTTP transport, device-code and Xbox flows into impl/ - refactor(pvpcooldowns): extract local item-rule engine and defaults into impl/PvpCooldownRules - refactor(lovisual): extract HUD/world render orchestration into HudRender helper - refactor(statuseffectheuristics): extract palette/inference into ParticlePalette and color utils into ParticleColors - refactor(dropesp): extract overlay/label render subsystem into impl/DropEspOverlayRenderer - refactor(proxy): extract SOCKS handshake message builders into ProxyProtocolMessages - refactor(eagleutil): promote EdgeRecovery controller and RecoveryMode to top-level class
96 lines
5.9 KiB
Markdown
96 lines
5.9 KiB
Markdown
# Frontend Architecture (продумано заранее, реализация — следующий план)
|
||
|
||
> Статус: структура согласована до написания implementation-плана фронтенда,
|
||
> чтобы план сразу проектировался под правильные границы, а не переписывался
|
||
> после первого клубка спагетти. Стек: React + Vite + TypeScript + Tailwind
|
||
> (см. `TODO.md`, Фаза 10). Правила платформы (≤250 строк/файл и т.д.) — там же.
|
||
|
||
## Принцип: структура по фичам, не по типу файла
|
||
|
||
Раскладывать `src/` на `/components`, `/hooks`, `/services`, `/types` вперемешку —
|
||
самая частая ошибка в React-проектах: одна фича размазывается по всему дереву
|
||
папок, и её нельзя удалить или вынести, не задев остальное. Вместо этого —
|
||
каждая фича владеет всем, что ей нужно, в одной папке.
|
||
|
||
```
|
||
frontend/src/
|
||
features/
|
||
auth/ # регистрация/логин, device-link экран
|
||
components/
|
||
hooks/
|
||
api.ts # вызовы к accounts-service через gateway
|
||
types.ts
|
||
configs/ # 4 слота, share-коды, витрина
|
||
components/
|
||
hooks/
|
||
api.ts
|
||
types.ts
|
||
avatars/
|
||
admin/ # /admin, видим только role=admin
|
||
shared/ # только то, что реально используют 2+ фичи
|
||
components/ # кнопки, инпуты, модалки — дизайн-система
|
||
hooks/ # useAuth (общий контекст сессии), useDebounce и т.п.
|
||
api/
|
||
client.ts # общий fetch-wrapper: base URL gateway, JWT в заголовке,
|
||
# обработка 401 (refresh) и 429 (rate-limit) в одном месте
|
||
types.ts # общие DTO, если совпадают на нескольких фичах
|
||
pages/ # роуты верхнего уровня, тонкие — просто собирают
|
||
# фичи в layout, никакой бизнес-логики
|
||
App.tsx
|
||
main.tsx
|
||
```
|
||
|
||
Правило раздела shared/feature: если код используется ровно в одной фиче —
|
||
он живёт в этой фиче, а не в `shared/`. Переносить в `shared/` только когда
|
||
появился второй потребитель — не заранее "на всякий случай" (YAGNI).
|
||
|
||
**Лимиты из правил платформы (`TODO.md`) действуют и тут**: ≤250 строк на
|
||
файл, ≤4 файла на папку (подпапки не считаются) — если в `components/`
|
||
внутри фичи появляется 5-й файл, выносим смысловую подпапку, а не копим.
|
||
|
||
## Антипаттерны, которых сознательно избегаем
|
||
|
||
- **Barrel-файлы `index.ts` на каждую папку** — удобны на вид, но ломают
|
||
tree-shaking и IDE go-to-definition на больших проектах; экспортируем
|
||
напрямую из файла, где определено
|
||
- **Prop drilling через 4+ уровня** — если проп передаётся через компоненты,
|
||
которым он сам не нужен (просто транзитом) — это сигнал на React Context
|
||
(для auth-сессии) или на подъём компонента ниже по дереву, а не терпеть
|
||
drilling
|
||
- **Бизнес-логика в `pages/`** — страницы только компонуют фичи и layout;
|
||
если в файле страницы появляется `fetch`/сложная derived-логика — она
|
||
переезжает в соответствующую фичу
|
||
- **Один гигантский `api.ts` на весь проект** — обращения к API живут в
|
||
папке своей фичи (`features/configs/api.ts` и т.д.), общий только
|
||
low-level `shared/api/client.ts` (fetch-wrapper)
|
||
- **any вместо нормальных типов** — DTO с бэкенда типизируются по контрактам
|
||
из `backend/PLAN.md` (Task 6: `RegisterResponse`, `LoginResponse` и т.д.),
|
||
не `any`/`unknown` без сужения
|
||
|
||
## Тестирование
|
||
Тесты живут в подпапке `tests/` внутри фичи (или `shared/*`), которую они
|
||
проверяют — не рядом с файлом (`Component.test.tsx`) и не в отдельном дереве
|
||
на верхнем уровне. Это всё ещё удаляется вместе с фичей при её удалении/
|
||
переносе, но не съедает бюджет "≤4 файла на папку" — колокация `X.test.tsx`
|
||
рядом с `X.tsx` вдвое сокращала бы вместимость каждой папки под этим правилом.
|
||
|
||
```
|
||
frontend/src/
|
||
features/
|
||
auth/
|
||
components/
|
||
hooks/
|
||
api.ts
|
||
types.ts
|
||
tests/
|
||
api.test.ts
|
||
components.test.tsx
|
||
shared/
|
||
ui/
|
||
Button.tsx
|
||
TextField.tsx
|
||
tests/
|
||
ui.test.tsx
|
||
```
|
||
|
||
Источники: [Robin Wieruch — React Folder Structure Best Practices 2026](https://www.robinwieruch.de/react-folder-structure/), [Mastering Modern React + Vite Folder Structure, Medium](https://sandeshrathnayake.medium.com/mastering-modern-react-vite-folder-structure-a-production-ready-guide-for-scalable-applications-9ad8e233f8b9).
|