Compare commits

...

3 Commits

Author SHA1 Message Date
semantic-release-bot
3cef4fcbac chore(release): 3.22.1 [skip ci]
## [3.22.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.22.0...v3.22.1) (2025-10-16)

### Bug Fixes

* **arcade:** add Number Guesser to game config helpers ([7d1a351](7d1a351ed6))
* **nav:** update types for registry games with nullable gameName ([a51e539](a51e539d02))
2025-10-16 00:16:26 +00:00
Thomas Hallock
a51e539d02 fix(nav): update types for registry games with nullable gameName
Fixes TypeScript errors introduced by registry game system:
- Allow gameName to be string | null in nav component types
- Update RecentRoom, AddPlayerButton, GameContextNav, ArcadeRoomInfo interfaces
- Convert null to undefined where needed for legacy function calls
- Fix GameTitleMenu showMenu prop
- Update JoinRoomModal to use separate useGetRoomByCode and useJoinRoom hooks

These changes allow rooms to exist without a selected game (gameName = null).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 19:15:32 -05:00
Thomas Hallock
7d1a351ed6 fix(arcade): add Number Guesser to game config helpers
Fixes server-side session creation for Number Guesser:
- Import DEFAULT_NUMBER_GUESSER_CONFIG
- Add case for 'number-guesser' in getDefaultGameConfig()
- Add validation for number-guesser config
- Include arcade-games validators in server TypeScript build

This resolves the "Unknown game: number-guesser" error when creating sessions.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-15 19:15:32 -05:00
8 changed files with 50 additions and 11 deletions

View File

@@ -1,3 +1,11 @@
## [3.22.1](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.22.0...v3.22.1) (2025-10-16)
### Bug Fixes
* **arcade:** add Number Guesser to game config helpers ([7d1a351](https://github.com/antialias/soroban-abacus-flashcards/commit/7d1a351ed6a1442ae34f6b75d46039bfa77a921b))
* **nav:** update types for registry games with nullable gameName ([a51e539](https://github.com/antialias/soroban-abacus-flashcards/commit/a51e539d023681daf639ec104e79079c8ceec98e))
## [3.22.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v3.21.0...v3.22.0) (2025-10-16)

View File

@@ -26,7 +26,7 @@ interface AddPlayerButtonProps {
// Context-aware: show different content based on room state
isInRoom?: boolean
// Game info for room creation
gameName?: 'matching' | 'memory-quiz' | 'complement-race'
gameName?: string | null
}
export function AddPlayerButton({
@@ -38,7 +38,7 @@ export function AddPlayerButton({
activeTab: activeTabProp,
setActiveTab: setActiveTabProp,
isInRoom = false,
gameName = 'Arcade',
gameName = null,
}: AddPlayerButtonProps) {
const popoverRef = React.useRef<HTMLDivElement>(null)
const router = useRouter()

View File

@@ -28,7 +28,7 @@ interface NetworkPlayer {
interface ArcadeRoomInfo {
roomId?: string
roomName?: string
gameName: string
gameName: string | null
playerCount: number
joinCode?: string
}
@@ -200,6 +200,7 @@ export function GameContextNav({
onSetup={onSetup}
onNewGame={onNewGame}
onQuit={onExitSession}
showMenu={true}
/>
<div style={{ marginLeft: 'auto' }}>
<GameModeIndicator
@@ -287,7 +288,7 @@ export function GameContextNav({
playerScores={playerScores}
playerStreaks={playerStreaks}
roomId={roomInfo?.roomId}
currentUserId={currentUserId}
currentUserId={currentUserId ?? undefined}
isCurrentUserHost={isCurrentUserHost}
/>
))}

View File

@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
import { io } from 'socket.io-client'
import { Modal } from '@/components/common/Modal'
import type { schema } from '@/db'
import { useRoomData } from '@/hooks/useRoomData'
import { useGetRoomByCode, useJoinRoom } from '@/hooks/useRoomData'
export interface JoinRoomModalProps {
/**
@@ -25,7 +25,8 @@ export interface JoinRoomModalProps {
* Modal for joining a room by entering a 6-character code
*/
export function JoinRoomModal({ isOpen, onClose, onSuccess }: JoinRoomModalProps) {
const { getRoomByCode, joinRoom } = useRoomData()
const { mutateAsync: getRoomByCode } = useGetRoomByCode()
const { mutate: joinRoom } = useJoinRoom()
const [code, setCode] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')

View File

@@ -4,7 +4,7 @@ import { getRoomDisplayWithEmoji } from '@/utils/room-display'
interface RecentRoom {
code: string
name: string | null
gameName: string
gameName: string | null
joinedAt: number
}
@@ -105,7 +105,7 @@ export function RecentRoomsList({ onSelectRoom }: RecentRoomsListProps) {
{getRoomDisplayWithEmoji({
name: room.name,
code: room.code,
gameName: room.gameName,
gameName: room.gameName ?? undefined,
})}
</span>
</div>
@@ -133,7 +133,7 @@ export function RecentRoomsList({ onSelectRoom }: RecentRoomsListProps) {
export function addToRecentRooms(room: {
code: string
name: string | null
gameName: string
gameName: string | null
}): void {
try {
const stored = localStorage.getItem(STORAGE_KEY)

View File

@@ -14,6 +14,7 @@ import {
DEFAULT_MATCHING_CONFIG,
DEFAULT_MEMORY_QUIZ_CONFIG,
DEFAULT_COMPLEMENT_RACE_CONFIG,
DEFAULT_NUMBER_GUESSER_CONFIG,
} from './game-configs'
/**
@@ -27,6 +28,8 @@ function getDefaultGameConfig(gameName: GameName): GameConfigByName[GameName] {
return DEFAULT_MEMORY_QUIZ_CONFIG
case 'complement-race':
return DEFAULT_COMPLEMENT_RACE_CONFIG
case 'number-guesser':
return DEFAULT_NUMBER_GUESSER_CONFIG
default:
throw new Error(`Unknown game: ${gameName}`)
}
@@ -194,6 +197,18 @@ export function validateGameConfig(gameName: GameName, config: any): boolean {
// TODO: Add validation when complement-race settings are defined
return typeof config === 'object' && config !== null
case 'number-guesser':
return (
typeof config === 'object' &&
config !== null &&
typeof config.minNumber === 'number' &&
typeof config.maxNumber === 'number' &&
typeof config.roundsToWin === 'number' &&
config.minNumber >= 1 &&
config.maxNumber > config.minNumber &&
config.roundsToWin >= 1
)
default:
return false
}

View File

@@ -19,10 +19,24 @@
"src/db/schema/**/*.ts",
"src/db/migrate.ts",
"src/lib/arcade/**/*.ts",
"src/arcade-games/**/Validator.ts",
"src/arcade-games/**/types.ts",
"src/app/games/matching/context/types.ts",
"src/app/games/matching/utils/cardGeneration.ts",
"src/app/games/matching/utils/matchValidation.ts",
"src/app/arcade/memory-quiz/types.ts",
"src/socket-server.ts"
],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts"]
"exclude": [
"node_modules",
"dist",
"src/components/**/*",
"src/contexts/**/*",
"src/hooks/**/*",
"src/stories/**/*",
"src/utils/**/*",
"**/*.test.ts",
"**/*.test.tsx",
"**/*.spec.ts"
]
}

View File

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