Compare commits

..

2 Commits

Author SHA1 Message Date
semantic-release-bot
d896e95bb5 chore(release): 4.2.2 [skip ci]
## [4.2.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.2.1...v4.2.2) (2025-10-16)

### Code Refactoring

* **types:** consolidate type system - eliminate fragmentation ([0726176](0726176e4d))
2025-10-16 11:52:14 +00:00
Thomas Hallock
0726176e4d refactor(types): consolidate type system - eliminate fragmentation
Implements "Option A: Single Source of Truth" from type audit recommendations.

**Phase 1: Consolidate GameValidator**
- Remove redundant GameValidator re-declaration from SDK types
- SDK now properly re-exports GameValidator from validation types
- Eliminates confusion about which validator interface to use

**Phase 2: Eliminate Move Type Duplication**
- Remove duplicate game-specific move interfaces from validation/types.ts
- Add re-exports of game move types from their source modules
- Maintains single source of truth (game types) while providing convenient access

**Changes:**
- `src/lib/arcade/game-sdk/types.ts`: Import & re-export GameValidator instead of re-declaring
- `src/lib/arcade/validation/types.ts`: Replace duplicate move interfaces with re-exports
- `__tests__/room-realtime-updates.e2e.test.ts`: Fix socket-server import path

**Impact:**
- Zero new type errors introduced
- All existing functionality preserved
- Clear ownership: game types are source of truth
- Improved maintainability: changes in one place

**Verification:**
- TypeScript compilation:  No new errors
- Server build:  Successful
- All pre-existing errors unchanged (AbacusReact module resolution, etc.)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 06:51:20 -05:00
6 changed files with 37 additions and 140 deletions

View File

@@ -1,3 +1,10 @@
## [4.2.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.2.1...v4.2.2) (2025-10-16)
### Code Refactoring
* **types:** consolidate type system - eliminate fragmentation ([0726176](https://github.com/antialias/soroban-abacus-flashcards/commit/0726176e4d2666f6f3a289f01736747c33e93879))
## [4.2.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.2.0...v4.2.1) (2025-10-16)

View File

@@ -86,7 +86,10 @@
"Bash(do sed -i '' \"s|from ''../context/MemoryPairsContext''|from ''../Provider''|g\" \"$file\")",
"Bash(do sed -i '' \"s|from ''../../../../../styled-system/css''|from ''@/styled-system/css''|g\" \"$file\")",
"Bash(tee:*)",
"Bash(do sed -i '' \"s|from ''@/styled-system/css''|from ''../../../../styled-system/css''|g\" \"$file\")"
"Bash(do sed -i '' \"s|from ''@/styled-system/css''|from ''../../../../styled-system/css''|g\" \"$file\")",
"Bash(do echo \"=== $game ===\" echo \"Required files:\" ls -1 src/arcade-games/$game/)",
"Bash(do echo \"=== $game%/ ===\")",
"Bash(ls:*)"
],
"deny": [],
"ask": []

View File

@@ -9,7 +9,7 @@ import { afterEach, beforeEach, describe, expect, it, afterAll, beforeAll } from
import { db, schema } from '../src/db'
import { createRoom } from '../src/lib/arcade/room-manager'
import { addRoomMember } from '../src/lib/arcade/room-membership'
import { initializeSocketServer } from '../socket-server'
import { initializeSocketServer } from '../src/socket-server'
import type { Server as SocketIOServerType } from 'socket.io'
/**

View File

@@ -7,15 +7,18 @@ import type { ReactNode } from 'react'
import type { GameManifest } from '../manifest-schema'
import type {
GameMove as BaseGameMove,
GameValidator as BaseGameValidator,
ValidationContext,
ValidationResult,
GameValidator,
} from '../validation/types'
/**
* Re-export base validation types from arcade system
*/
export type { GameMove, ValidationContext, ValidationResult } from '../validation/types'
export type {
GameMove,
GameValidator,
ValidationContext,
ValidationResult,
} from '../validation/types'
export { TEAM_MOVE } from '../validation/types'
export type { TeamMoveSentinel } from '../validation/types'
@@ -31,17 +34,6 @@ export type GameConfig = Record<string, unknown>
*/
export type GameState = Record<string, unknown>
/**
* Game validator interface
* Games must implement this to validate moves server-side
*/
export interface GameValidator<TState = GameState, TMove extends BaseGameMove = BaseGameMove>
extends BaseGameValidator<TState, TMove> {
validateMove(state: TState, move: TMove, context?: ValidationContext): ValidationResult
isGameComplete(state: TState): boolean
getInitialState(config: unknown): TState
}
/**
* Provider component interface
* Each game provides a React context provider that wraps the game UI

View File

@@ -33,130 +33,25 @@ export interface GameMove {
data: unknown
}
// Matching game specific moves
export interface MatchingFlipCardMove extends GameMove {
type: 'FLIP_CARD'
data: {
cardId: string
}
}
/**
* Re-export game-specific move types from their respective modules
* This maintains a single source of truth (game types) while providing
* convenient access for validation code.
*/
export type { MatchingMove } from '@/arcade-games/matching/types'
export type { MemoryQuizMove } from '@/arcade-games/memory-quiz/types'
export type { NumberGuesserMove } from '@/arcade-games/number-guesser/types'
export type { MathSprintMove } from '@/arcade-games/math-sprint/types'
export interface MatchingStartGameMove extends GameMove {
type: 'START_GAME'
data: {
activePlayers: string[] // Player IDs (UUIDs)
cards?: any[] // GameCard type from context
playerMetadata?: { [playerId: string]: any } // Player metadata for cross-user visibility
}
}
/**
* Re-export game-specific state types from their respective modules
*/
export type { MatchingState } from '@/arcade-games/matching/types'
export type { MemoryQuizState } from '@/arcade-games/memory-quiz/types'
export type { NumberGuesserState } from '@/arcade-games/number-guesser/types'
export type { MathSprintState } from '@/arcade-games/math-sprint/types'
export interface MatchingClearMismatchMove extends GameMove {
type: 'CLEAR_MISMATCH'
data: Record<string, never>
}
// Standard setup moves - pattern for all arcade games
export interface MatchingGoToSetupMove extends GameMove {
type: 'GO_TO_SETUP'
data: Record<string, never>
}
export interface MatchingSetConfigMove extends GameMove {
type: 'SET_CONFIG'
data: {
field: 'gameType' | 'difficulty' | 'turnTimer'
value: any
}
}
export interface MatchingResumeGameMove extends GameMove {
type: 'RESUME_GAME'
data: Record<string, never>
}
export interface MatchingHoverCardMove extends GameMove {
type: 'HOVER_CARD'
data: {
cardId: string | null // null when mouse leaves card
}
}
export type MatchingGameMove =
| MatchingFlipCardMove
| MatchingStartGameMove
| MatchingClearMismatchMove
| MatchingGoToSetupMove
| MatchingSetConfigMove
| MatchingResumeGameMove
| MatchingHoverCardMove
// Memory Quiz game specific moves
export interface MemoryQuizStartQuizMove extends GameMove {
type: 'START_QUIZ'
data: {
quizCards: any[] // QuizCard type from memory-quiz types
}
}
export interface MemoryQuizNextCardMove extends GameMove {
type: 'NEXT_CARD'
data: Record<string, never>
}
export interface MemoryQuizShowInputPhaseMove extends GameMove {
type: 'SHOW_INPUT_PHASE'
data: Record<string, never>
}
export interface MemoryQuizAcceptNumberMove extends GameMove {
type: 'ACCEPT_NUMBER'
data: {
number: number
}
}
export interface MemoryQuizRejectNumberMove extends GameMove {
type: 'REJECT_NUMBER'
data: Record<string, never>
}
export interface MemoryQuizSetInputMove extends GameMove {
type: 'SET_INPUT'
data: {
input: string
}
}
export interface MemoryQuizShowResultsMove extends GameMove {
type: 'SHOW_RESULTS'
data: Record<string, never>
}
export interface MemoryQuizResetQuizMove extends GameMove {
type: 'RESET_QUIZ'
data: Record<string, never>
}
export interface MemoryQuizSetConfigMove extends GameMove {
type: 'SET_CONFIG'
data: {
field: 'selectedCount' | 'displayTime' | 'selectedDifficulty' | 'playMode'
value: any
}
}
export type MemoryQuizGameMove =
| MemoryQuizStartQuizMove
| MemoryQuizNextCardMove
| MemoryQuizShowInputPhaseMove
| MemoryQuizAcceptNumberMove
| MemoryQuizRejectNumberMove
| MemoryQuizSetInputMove
| MemoryQuizShowResultsMove
| MemoryQuizResetQuizMove
| MemoryQuizSetConfigMove
// Generic game state union
// Generic game state union (for backwards compatibility)
export type GameState = MemoryPairsState | SorobanQuizState // Add other game states as union later
/**

View File

@@ -1,6 +1,6 @@
{
"name": "soroban-monorepo",
"version": "4.2.1",
"version": "4.2.2",
"private": true,
"description": "Beautiful Soroban Flashcard Generator - Monorepo",
"workspaces": [