docs: refresh ARCHITECTURE + CLAUDE with this session's work

- 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).
This commit is contained in:
simoleo89
2026-05-11 22:47:35 +02:00
parent 8b79233059
commit 7cf01b0947
2 changed files with 59 additions and 9 deletions
+2 -2
View File
@@ -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.
+57 -7
View File
@@ -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/<area>/<feature>/` (views) +
`src/hooks/<area>/<feature?>/` (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`