Updated CLAUDE.md files with: - Current test counts and status - Session injection pattern documentation - New module references and architecture notes - Updated Phase status (3E-Final complete) - Enhanced troubleshooting guides Files updated: - Root CLAUDE.md: Project overview and phase status - backend/CLAUDE.md: Backend overview with test counts - backend/README.md: Quick start and development guide - backend/app/api/CLAUDE.md: API routes documentation - backend/app/database/CLAUDE.md: Session injection docs - backend/app/utils/CLAUDE.md: Utilities documentation - backend/tests/CLAUDE.md: Testing patterns and policy - frontend-sba/CLAUDE.md: Frontend overview - frontend-sba/store/CLAUDE.md: Store patterns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
147 lines
3.7 KiB
Markdown
147 lines
3.7 KiB
Markdown
# Store Directory
|
|
|
|
Pinia stores for centralized state management. All stores use Composition API syntax.
|
|
|
|
## Available Stores
|
|
|
|
### game.ts - Active Game State
|
|
**Purpose**: Central state for real-time gameplay, synchronized via WebSocket.
|
|
|
|
**Key State**:
|
|
```typescript
|
|
gameState: GameState | null // Full game state from backend
|
|
homeLineup: Lineup[] // Cached home team roster
|
|
awayLineup: Lineup[] // Cached away team roster
|
|
playHistory: PlayResult[] // Play-by-play history
|
|
currentDecisionPrompt: DecisionPrompt | null
|
|
pendingRoll: RollData | null // Manual mode dice roll
|
|
```
|
|
|
|
**Critical Getters**:
|
|
```typescript
|
|
// Team determination (mirrors backend logic)
|
|
battingTeamId // away if top, home if bottom
|
|
fieldingTeamId // home if top, away if bottom
|
|
|
|
// Current players (LineupPlayerState)
|
|
currentBatter
|
|
currentPitcher
|
|
currentCatcher
|
|
|
|
// Decision state
|
|
needsDefensiveDecision
|
|
needsOffensiveDecision
|
|
canRollDice
|
|
canSubmitOutcome
|
|
```
|
|
|
|
**Player Lookup Method**:
|
|
```typescript
|
|
// Critical: Joins LineupPlayerState with full Lineup data
|
|
findPlayerInLineup(lineupId: number): Lineup | undefined
|
|
```
|
|
|
|
### auth.ts - Authentication
|
|
**Purpose**: Discord OAuth state with HttpOnly cookie-based authentication.
|
|
|
|
**Key State**: `currentUser`, `isAuthenticated`
|
|
|
|
**Critical Pattern - SSR Cookie Forwarding**:
|
|
```typescript
|
|
// checkAuth() must forward cookies during SSR
|
|
async function checkAuth(): Promise<boolean> {
|
|
const headers: Record<string, string> = {}
|
|
if (import.meta.server) {
|
|
const event = useRequestEvent()
|
|
const cookieHeader = event?.node.req.headers.cookie
|
|
if (cookieHeader) {
|
|
headers['Cookie'] = cookieHeader // Forward to backend
|
|
}
|
|
}
|
|
const response = await $fetch('/api/auth/me', {
|
|
credentials: 'include',
|
|
headers,
|
|
})
|
|
}
|
|
```
|
|
|
|
**API Calls Pattern**:
|
|
```typescript
|
|
// ALL API calls must use credentials: 'include'
|
|
const response = await $fetch('/api/games/', {
|
|
credentials: 'include', // Sends HttpOnly cookies
|
|
})
|
|
|
|
// NEVER use Authorization header - tokens are in cookies
|
|
```
|
|
|
|
**Reference**: See `COOKIE_AUTH_IMPLEMENTATION.md` for complete auth flow documentation.
|
|
|
|
### ui.ts - UI State
|
|
**Purpose**: Toasts, modals, loading states.
|
|
|
|
**Key Methods**: `showSuccess()`, `showError()`, `showWarning()`, `showInfo()`
|
|
|
|
## Data Resolution Pattern
|
|
|
|
Game state contains minimal `LineupPlayerState`:
|
|
```typescript
|
|
interface LineupPlayerState {
|
|
lineup_id: number // Key for lookup
|
|
card_id: number
|
|
position: string
|
|
// NO player name, headshot, etc.
|
|
}
|
|
```
|
|
|
|
Store caches full `Lineup` with nested player:
|
|
```typescript
|
|
interface Lineup {
|
|
lineup_id: number
|
|
player: {
|
|
id: number
|
|
name: string
|
|
headshot: string
|
|
}
|
|
}
|
|
```
|
|
|
|
**Resolution**:
|
|
```typescript
|
|
const batterState = gameStore.currentBatter // LineupPlayerState
|
|
const batterLineup = gameStore.findPlayerInLineup( // Full Lineup
|
|
batterState.lineup_id
|
|
)
|
|
const name = batterLineup?.player.name // "Mike Trout"
|
|
```
|
|
|
|
## Store Patterns
|
|
|
|
### Nuxt 4 Import Requirement
|
|
```typescript
|
|
// ALWAYS explicitly import stores
|
|
import { useGameStore } from '~/store/game'
|
|
const gameStore = useGameStore()
|
|
|
|
// NEVER rely on auto-imports (breaks in Nuxt 4)
|
|
```
|
|
|
|
### Readonly State
|
|
All state refs are exposed as `readonly()` to prevent direct mutation:
|
|
```typescript
|
|
return {
|
|
gameState: readonly(gameState), // Can't do gameStore.gameState.value = x
|
|
setGameState, // Use action instead
|
|
}
|
|
```
|
|
|
|
### Team Determination Logic
|
|
```typescript
|
|
// Same logic as backend state_manager.py
|
|
const battingTeamId = computed(() => {
|
|
return gameState.value.half === 'top'
|
|
? gameState.value.away_team_id // Top: away bats
|
|
: gameState.value.home_team_id // Bottom: home bats
|
|
})
|
|
```
|