Compare commits

...

3 Commits

Author SHA1 Message Date
semantic-release-bot
c7a660c153 chore(release): 2.19.0 [skip ci]
## [2.19.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v2.18.0...v2.19.0) (2025-10-10)

### Features

* add player ownership helper to player-manager API ([6b59a82](6b59a828aa))

### Code Refactoring

* migrate session-manager.ts to use centralized player ownership ([d3b7cc2](d3b7cc25ca))
2025-10-10 13:57:10 +00:00
Thomas Hallock
6b59a828aa feat: add player ownership helper to player-manager API
Added getPlayerOwnershipMap() as a convenience re-export of the
centralized buildPlayerOwnershipMap() utility.

This allows modules to access player ownership data through the
player-manager API, which is the natural home for player-related
server-side operations.

New function:
- getPlayerOwnershipMap(roomId?) - Returns PlayerOwnershipMap

Benefits:
- Consistent API: player data + ownership through same module
- Discovery: developers naturally look in player-manager for player ops
- Flexibility: can add room-filtering logic in future if needed
- Documentation: JSDoc example shows usage pattern

Example usage:
  const ownership = await getPlayerOwnershipMap()
  const isOwned = ownership[playerId] === userId

This is phase 3 of the player ownership centralization plan.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-10 08:56:15 -05:00
Thomas Hallock
d3b7cc25ca refactor: migrate session-manager.ts to use centralized player ownership
Replaced inline player ownership logic with centralized utilities from
player-ownership.ts module.

Changes:
- Import buildPlayerOwnershipMap() and getUserIdFromGuestId() from
  player-ownership module
- Remove duplicate getUserIdFromGuestId() function (now exported from module)
- Replace inline DB query with buildPlayerOwnershipMap() call
- Use PlayerOwnershipMap type for consistency

Benefits:
- Eliminates 10 lines of duplicated code
- Single source of truth for ownership logic
- Consistent with validator and other components
- Better type safety with shared types

Before: Lines 232-238 built ownership map inline
After: Line 226 calls centralized utility

This is phase 2 of the player ownership centralization plan.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-10 08:55:24 -05:00
4 changed files with 40 additions and 21 deletions

View File

@@ -1,3 +1,15 @@
## [2.19.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v2.18.0...v2.19.0) (2025-10-10)
### Features
* add player ownership helper to player-manager API ([6b59a82](https://github.com/antialias/soroban-abacus-flashcards/commit/6b59a828aabe687abb797c1f1d69d8a4d0abe49b))
### Code Refactoring
* migrate session-manager.ts to use centralized player ownership ([d3b7cc2](https://github.com/antialias/soroban-abacus-flashcards/commit/d3b7cc25caee7e005de046792202aa474edbc90f))
## [2.18.0](https://github.com/antialias/soroban-abacus-flashcards/compare/v2.17.3...v2.18.0) (2025-10-10)

View File

@@ -6,6 +6,7 @@
import { and, eq } from 'drizzle-orm'
import { db, schema } from '@/db'
import type { Player } from '@/db/schema/players'
import { type PlayerOwnershipMap, buildPlayerOwnershipMap } from './player-ownership'
/**
* Get all players for a user (regardless of isActive status)
@@ -128,3 +129,21 @@ export async function getPlayers(playerIds: string[]): Promise<Player[]> {
return players
}
/**
* Get player ownership map for a room
*
* Convenience re-export of the centralized player ownership utility.
* This allows other modules to get player ownership data through
* the player-manager API.
*
* @param roomId - Optional room ID (currently unused by underlying utility)
* @returns Promise resolving to playerOwnership map (playerId -> userId)
*
* @example
* const ownership = await getPlayerOwnershipMap()
* const isOwned = ownership[playerId] === userId
*/
export async function getPlayerOwnershipMap(roomId?: string): Promise<PlayerOwnershipMap> {
return buildPlayerOwnershipMap(roomId)
}

View File

@@ -5,6 +5,11 @@
import { eq } from 'drizzle-orm'
import { db, schema } from '@/db'
import {
buildPlayerOwnershipMap,
getUserIdFromGuestId,
type PlayerOwnershipMap,
} from './player-ownership'
import { type GameMove, type GameName, getValidator } from './validation'
export interface CreateSessionOptions {
@@ -25,18 +30,6 @@ export interface SessionUpdateResult {
const TTL_HOURS = 24
/**
* Helper: Get database user ID from guest ID
* The API uses guestId (from cookies) but database FKs use the internal user.id
*/
async function getUserIdFromGuestId(guestId: string): Promise<string | undefined> {
const user = await db.query.users.findFirst({
where: eq(schema.users.guestId, guestId),
columns: { id: true },
})
return user?.id
}
/**
* Get arcade session by room ID (for room-based multiplayer games)
* Returns the shared session for all room members
@@ -215,7 +208,7 @@ export async function applyGameMove(
})
// Fetch player ownership for authorization checks (room-based games)
let playerOwnership: Record<string, string> | undefined
let playerOwnership: PlayerOwnershipMap | undefined
let internalUserId: string | undefined
if (session.roomId) {
try {
@@ -229,13 +222,8 @@ export async function applyGameMove(
}
}
const players = await db.query.players.findMany({
columns: {
id: true,
userId: true,
},
})
playerOwnership = Object.fromEntries(players.map((p) => [p.id, p.userId]))
// Use centralized player ownership utility
playerOwnership = await buildPlayerOwnershipMap(session.roomId)
console.log('[SessionManager] Player ownership map:', playerOwnership)
console.log('[SessionManager] Internal userId for authorization:', internalUserId)
} catch (error) {

View File

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