veza/apps/web/docs/ZUSTAND_STORES_AUDIT.md

8.6 KiB

Zustand Stores Audit

Date: 2026-01-11
Action: 4.5.1.1 - List all Zustand stores
Status: Complete

Summary

This document lists all Zustand stores found in the codebase, their locations, purposes, and key characteristics.

Stores Found

1. UI Store (apps/web/src/stores/ui.ts)

  • Export: useUIStore
  • Purpose: UI state management (theme, language, sidebar, notifications)
  • Middlewares: persist, devtools, broadcastSync
  • State Type: UIStore (UIState & UIActions)
  • Key State:
    • theme: 'light' | 'dark' | 'system'
    • language: 'en' | 'fr'
    • sidebarOpen: boolean
    • notifications: Notification[]
  • Category: UI State (appropriate for Zustand)
  • Migration Priority: Low (UI state should stay in Zustand)

2. Library Store (apps/web/src/stores/library.ts)

  • Export: useLibraryStore
  • Purpose: Library items, favorites, pagination state
  • Middlewares: persist, devtools, stateMiddleware, undoRedo
  • State Type: LibraryStore (LibraryState & LibraryActions & WithUndoRedo)
  • Key State:
    • items: NormalizedState<LibraryItem> ⚠️ Domain Data
    • favorites: NormalizedState<LibraryItem> ⚠️ Domain Data
    • pagination: { page, limit, total, hasNext, hasPrev } ⚠️ Domain Data
    • isLoading: boolean
    • error: ApiError | null
  • Category: ⚠️ Domain Data (should migrate to React Query)
  • Migration Priority: High (contains domain data that should be server state)

3. Chat Store (apps/web/src/stores/chat.ts)

  • Export: useChatStore
  • Purpose: Chat conversations, messages, typing indicators
  • Middlewares: persist, devtools
  • State Type: ChatStore (ChatState & ChatActions)
  • Key State:
    • conversations: Conversation[] ⚠️ Domain Data
    • currentConversation: Conversation | null UI State
    • messages: Record<string, ChatMessage[]> ⚠️ Domain Data
    • typingUsers: Record<string, string[]> UI State (ephemeral)
    • isConnected: boolean UI State
    • isLoading: boolean
    • error: string | null
  • Category: ⚠️ Mixed (domain data + UI state)
  • Migration Priority: Medium (domain data should migrate to React Query, UI state can stay)

4. Cart Store (apps/web/src/stores/cartStore.ts)

  • Export: useCartStore
  • Purpose: Shopping cart items and operations
  • Middlewares: persist
  • State Type: CartStore (CartState)
  • Key State:
    • items: CartItem[] UI State (client-side cart before checkout)
    • Actions: addItem, removeItem, updateQuantity, clearCart, getTotal, getItemCount
  • Category: UI State (appropriate for Zustand - client-side cart)
  • Migration Priority: Low (cart is client-side state before checkout)
  • Analysis:
    • Cart items are temporary client-side state before checkout
    • Not domain data - cart is created client-side, not fetched from server
    • Persisted to localStorage for user convenience
    • No server synchronization needed until checkout
    • Correctly categorized as UI state

5. Auth Store (apps/web/src/features/auth/store/authStore.ts)

  • Export: useAuthStore
  • Purpose: Authentication state (user, tokens, auth status)
  • Middlewares: persist, broadcastSync
  • State Type: AuthStore (AuthState & AuthActions)
  • Key State:
    • user: User | null ⚠️ Domain Data (should migrate to React Query)
    • isAuthenticated: boolean UI State (can stay)
    • isLoading: boolean
    • error: ApiError | null
    • _refreshUserPromise: Promise<void> | null (internal deduplication)
  • Category: ⚠️ Mixed (domain data + UI state)
  • Migration Priority: High (user data should migrate to React Query - Action 4.1.1.x)

6. Chat Store (Feature) (apps/web/src/features/chat/store/chatStore.ts)

  • Export: useChatStore (⚠️ DUPLICATE NAME with stores/chat.ts)
  • Purpose: Chat state management (feature-specific, uses Immer)
  • Middlewares: immer, devtools
  • State Type: Chat store with Immer middleware
  • Key State:
    • conversations: Conversation[] ⚠️ Domain Data
    • messages: Record<string, ChatMessage[]> ⚠️ Domain Data
    • currentConversationId: string | null UI State
    • typingUsers: Record<string, string[]> UI State
    • wsStatus: 'disconnected' | 'connecting' | 'connected' | 'error' UI State
  • Category: ⚠️ Domain Data (duplicate store - needs investigation)
  • Migration Priority: High (investigate which store is used, consolidate)
  • Note: stores/index.ts exports stores/chat.ts, but feature store exists separately

7. Player Store (apps/web/src/features/player/store/playerStore.ts)

  • Export: usePlayerStore (likely)
  • Purpose: Audio player state (current track, playback state, queue)
  • Middlewares: persist
  • State Type: Player store
  • Key State: (needs inspection)
  • Category: UI State (player state is client-side)
  • Migration Priority: Low (player state should stay in Zustand)

Store Locations

Centralized Stores (apps/web/src/stores/)

  1. ui.ts - UI Store
  2. library.ts - Library Store
  3. chat.ts - Chat Store
  4. cartStore.ts - Cart Store
  5. types.ts - Type definitions
  6. index.ts - Exports

Feature Stores (apps/web/src/features/*/store/)

  1. auth/store/authStore.ts - Auth Store
  2. chat/store/chatStore.ts - Chat Store (duplicate?)
  3. player/store/playerStore.ts - Player Store

Store Characteristics

Middleware Usage

  • persist: Used in 6/7 stores (UI, Library, Chat, Cart, Auth, Player)
  • devtools: Used in 3/7 stores (UI, Library, Chat)
  • broadcastSync: Used in 2/7 stores (UI, Auth)
  • stateMiddleware: Used in 1/7 stores (Library)
  • undoRedo: Used in 1/7 stores (Library)
  • immer: Used in 1/7 stores (Chat feature store)

Domain Data Stores (Should Migrate to React Query)

  1. Library Store - items, favorites, pagination
  2. Auth Store - user (Action 4.1.1.x in progress)
  3. Chat Store - conversations, messages

UI State Stores (Appropriate for Zustand)

  1. UI Store - Theme, language, sidebar, notifications
  2. Cart Store - Shopping cart items
  3. Player Store - Audio player state
  4. Auth Store - isAuthenticated flag

Mixed Stores (Need Partial Migration)

  1. Auth Store - user (domain) + isAuthenticated (UI)
  2. Chat Store - conversations/messages (domain) + currentConversation/typingUsers (UI)

Issues Identified

1. Duplicate Chat Stores ⚠️ CRITICAL

  • Store 1: apps/web/src/stores/chat.ts (exported in stores/index.ts)
    • Used by: ChatMessages.tsx, stateHydration.ts, storeSelectors.ts, stores.test.ts
    • Middlewares: persist, devtools
  • Store 2: apps/web/src/features/chat/store/chatStore.ts (feature-specific)
    • Used by: Most chat feature components (ChatSidebar, ChatPage, ChatInput, ChatRoom, CreateRoomDialog, useChat.ts, TypingIndicator)
    • Middlewares: immer, devtools
  • Problem: Both export useChatStore with same name, causing potential conflicts
  • Action Required:
    1. Determine which store is the source of truth
    2. Consolidate into single store
    3. Update all imports to use consolidated store
    4. Remove duplicate store

2. Domain Data in Zustand ⚠️

  • Library Store contains domain data (items, favorites)
  • Auth Store contains domain data (user)
  • Chat Store contains domain data (conversations, messages)
  • Action Required: Migrate domain data to React Query (Epic 4.1)

3. Complex Middleware Stack

  • Library Store uses stateMiddleware and undoRedo - may be unnecessary complexity
  • Action Required: Audit middleware usage (Action 4.1.2.x)

Migration Roadmap

Phase 1: High Priority (Domain Data)

  1. Auth Store - user → React Query (Action 4.1.1.x in progress)
  2. Library Store - items, favorites → React Query
  3. Chat Store - conversations, messages → React Query

Phase 2: Medium Priority (Cleanup)

  1. Investigate duplicate Chat stores
  2. Simplify middleware stacks
  3. Remove stateMiddleware if unnecessary

Phase 3: Low Priority (Keep in Zustand)

  1. UI Store - Keep (UI state)
  2. Cart Store - Keep (client-side cart)
  3. Player Store - Keep (player state)

Next Steps

  1. Action 4.5.1.1: List complete - 7 stores identified
  2. Action 4.5.1.2: Categorize stores (UI state vs domain data) - See categorization above
  3. Action 4.1.1.x: Migrate Auth Store user to React Query (in progress)
  4. Action 4.1.2.x: Migrate Library Store domain data to React Query
  5. Investigate duplicate Chat stores