From 7cf01b09473d849bda35cb39359d8c38fb75f15c Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Mon, 11 May 2026 22:47:35 +0200 Subject: [PATCH] docs: refresh ARCHITECTURE + CLAUDE with this session's work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pattern #2 (useNitroQuery): list the eight catalog-layer queries carved out of useCatalog this session (gift / groups / club offers / pet palette / marketplace / club gifts), plus the new useNitroEventInvalidator companion for server-push refresh. - Note ICatalogOptions deleted — the legacy 'catalogOptions' bag has no remaining fields after the migrations, useCatalog no longer exposes it. - New 'useCatalog decomposition (in progress)' table — what's been lifted to TanStack and what's deferred (page tree + Builders Club status, both core state slices that move with the data/actions split). - Pattern #4 (god-hook split): add the three new splits done this session (chat-input doorbell-style, wired-tools singleton-filter, translation singleton-filter inline). - Bump Vitest count 83 → 99 (added 16 cases on the useCatalogFavorites helpers). - Note the pure-module test convention: import from concrete file paths rather than the api barrel to avoid jsdom pulling in Pixi. - Typecheck baseline: client now reports 0 too (was 57 at last doc-write); the section's enumerated sweeps all landed. - CLAUDE.md: bump '77/77' references to '99/99' (both places). --- CLAUDE.md | 4 +-- docs/ARCHITECTURE.md | 64 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 638df31..b4300f4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -160,7 +160,7 @@ Login / Register / Forgot in `src/components/login/LoginView.tsx` use | Zustand | `NavigatorRoomCreatorView` (`useRoomCreatorStore`) | | God-hook split | `doorbell`, `poll`, `furni-chooser`, `user-chooser`, `friend-request` | | `WidgetErrorBoundary` | `RoomWidgetsView` umbrella | -| Vitest | 77/77 cases on pure helpers + the Zustand store | +| Vitest | 99/99 cases on pure helpers + the Zustand store | | Not yet | Notes | |---|---| @@ -196,7 +196,7 @@ Fix shapes documented; both are reasonable PRs on their own. - **Skip-motivated god-hook splits are fine** — when a hook's actions mutate internal state, document the reason in the commit message and move on rather than forcing a bad split. -- **`yarn test` must stay green** on every commit. Currently 77/77. +- **`yarn test` must stay green** on every commit. Currently 99/99. - **Lint baseline**: don't regress. Some pre-existing errors (`FC<{}>`, `IMessageEvent | undefined` redundant union in the local sandbox where the renderer SDK isn't installed) are out of scope here. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 13280af..f1049e4 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -360,11 +360,33 @@ The current branch (**`feat/react19-modernization`**, PR #2) has applied: devtools installed; `QueryClientProvider` mounted in `src/index.tsx`. Adapter at `src/api/nitro-query/createNitroQuery.ts` with `select`, `accept` (correlation-key filter), `timeoutMs`, `staleTime`, plus a - lower-level `awaitNitroResponse()` for imperative use. Pilots: - `OfferView`, `CatalogLayoutRoomAdsView`, `ModToolsChatlogView`, - `CfhChatlogView`, `useGiftConfiguration` (replaces the - `GiftWrappingConfigurationEvent` listener + eager composer dispatch - that lived in `useCatalog`; consumed directly by `CatalogGiftView`). + lower-level `awaitNitroResponse()` for imperative use. Companion at + `src/api/nitro-query/useNitroEventInvalidator.ts` invalidates a slot + whenever the server pushes the matching event unprompted — required + for queries whose data the server refreshes outside the request cycle + (e.g. ClubGiftInfoEvent after a gift claim). Pilots / sites: + - `OfferView` (targeted offer) + - `CatalogLayoutRoomAdsView` (room-ad list) + - `ModToolsChatlogView` / `CfhChatlogView` (correlated by roomId / ticketId) + - `useGiftConfiguration` — replaces the GiftWrappingConfigurationEvent + listener + eager composer dispatch that lived in `useCatalog` + - `useUserGroups` — consolidates 5 sites that each fired + CatalogGroupsComposer independently (2 wired views + 2 catalog + group widgets + useCatalog itself); now one query, dedup'd + - `useClubOffers(windowId)` — per-windowId query for the VIP / Builders + Club purchase pages, with accept() correlation filter + - `useSellablePetPalette(breed)` — per-breed pet palette, accept() + filter on parser.productCode + - `useMarketplaceConfiguration` — lifts a self-fetch out of + MarketplacePostOfferView + - `useClubGifts` — paired with `useNitroEventInvalidator` for the + server-push-after-SelectClubGift case +- **`ICatalogOptions` deleted** — useCatalog used to expose a + `catalogOptions` bag where multiple components stuffed unrelated + fetched data (groups, clubOffers, clubOffersByWindowId, petPalettes, + marketplaceConfiguration, clubGifts, giftConfiguration). Every field + is now its own TanStack query at the consumer site; the bag and the + interface are gone. - **Layout / feature folders** (proposal #3) — **rejected**. The existing `src/components///` (views) + `src/hooks///` (flat hook files) is the layout that @@ -424,11 +446,33 @@ The current branch (**`feat/react19-modernization`**, PR #2) has applied: dropped. - Main view: **4493 → 3544 lines** (−21%). +### `useCatalog` decomposition (in progress) + +The 1100-line god-hook owns the catalog page tree, current page, +offer selection, and a long tail of secondary fetches. Decomposition +strategy from ARCHITECTURE.md proposal #4 step 1: lift the +session-stable read-only fetches to TanStack queries first, then +split the remaining state ownership into `useCatalogData` / +`useCatalogUiState` / `useCatalogActions`. + +Status after this round of work: + +| Fetch | Migrated to | +|---|---| +| GiftWrappingConfiguration | `useGiftConfiguration()` | +| GuildMemberships | `useUserGroups()` | +| HabboClubOffers (per windowId) | `useClubOffers(windowId)` | +| SellablePetPalettes (per breed) | `useSellablePetPalette(breed)` | +| MarketplaceConfiguration | `useMarketplaceConfiguration()` | +| ClubGiftInfo | `useClubGifts()` (with `useNitroEventInvalidator`) | +| CatalogPagesList / CatalogPage | **deferred** — core state slice (rootNode / offersToNodes / currentPage), needs its own split-out store | +| BuildersClubFurniCount / SubscriptionStatus | **deferred** — read by the internal `getBuilderFurniPlaceableStatus` logic, moves with the data/actions split | + ### Tests - Vitest 3 + jsdom + `@testing-library/react` + `@testing-library/jest-dom` configured. Separate `vitest.config.mts` so the runner doesn't drag in the renderer SDK aliases from `vite.config.mjs`. -- **83 cases passing** across 7 test files: +- **99 cases passing** across 7 test files: - `WiredCreatorTools.helpers.test.ts` (18) — formatters + snapshot factory. - `navigatorRoomCreatorStore.test.ts` (4) — Zustand store invariants @@ -442,6 +486,12 @@ The current branch (**`feat/react19-modernization`**, PR #2) has applied: `LocalizeText` mock (cuts the transitive renderer-SDK import). - `dedupeBadges.test.ts` (6) — slot-preserving badge dedup (covers the helper used by the InfoStand pilot). + - `catalog-favorites.helpers.test.ts` (16) — localStorage parse + + v2→v3 migration + per-catalog-type storage-key routing. +- **Pure-module convention**: tests live in `tests/` and import from + concrete file paths (e.g. `../src/api/catalog/CatalogType`) rather + than the api barrel, so jsdom doesn't transitively load the renderer + SDK's Pixi-bound modules. - `yarn test` + `yarn test:watch` scripts added. ### Logic bug fixes @@ -468,7 +518,7 @@ The current branch (**`feat/react19-modernization`**, PR #2) has applied: call site). ### Typecheck baseline -- Repository-wide `tsgo` (TS 7 preview) errors driven down to **57** +- Repository-wide `tsgo` (TS 7 preview) errors driven down to **0** client-side and **0** renderer-side via a series of small targeted sweeps: - Framer-motion `Variants` typing on `ToolbarView` + `FriendsBarView`