Establishes foundation for migrating baseball simulation from Discord bot to web application using service-oriented architecture pattern. Key components: - FastAPI application structure with dependency injection - Service layer foundation with base classes and container - Comprehensive directory documentation with README files - PostgreSQL containerization with Docker Compose - Testing structure for unit/integration/e2e tests - Migration planning documentation - Rotating log configuration per user requirements Architecture follows Model/Service/Controller pattern to improve testability, maintainability, and scalability over original monolithic Discord app. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| api.py | ||
| auth.py | ||
| games.py | ||
| pages.py | ||
| README.md | ||
Routers Directory
This directory contains FastAPI route handlers following the Model/Service Architecture pattern. Routes are thin controllers that handle HTTP concerns and delegate business logic to services.
Architecture Pattern
Route Responsibilities
- HTTP Handling: Request/response processing, status codes
- Input Validation: Request data validation and parsing
- Service Delegation: Delegate business logic to services
- Response Formatting: Transform service results for HTTP responses
Design Principles
- Thin Controllers: Minimal logic, delegate to services
- Dependency Injection: Use FastAPI
Depends()for services - Error Handling: Transform service exceptions to HTTP errors
- Documentation: FastAPI auto-generates OpenAPI documentation
Current Files
auth.py
Authentication routes:
- Discord OAuth: Login redirect and callback handling
- Session Management: Login/logout functionality
- Uses:
AuthServicefor business logic
games.py
Game-related endpoints:
- Game Creation: Start new games
- Game Retrieval: Get game details and listings
- Uses:
GameServicefor business logic
api.py
JSON API endpoints for HTMX:
- Live Updates: Scoreboard and game state
- Player Actions: Execute gameplay actions
- Uses:
GameplayServicefor real-time updates
pages.py
HTML page routes with Jinja2 templates:
- Home Page: Main application entry point
- Game Interface: Live game viewing
- Template Rendering: Server-side HTML generation
Route Pattern Example
from fastapi import APIRouter, HTTPException
from app.services.service_container import GameServiceDep
router = APIRouter()
@router.post("/games/start")
async def start_game(
request: StartGameRequest,
game_service: GameServiceDep
):
"""Start a new game - delegates to GameService."""
try:
game = await game_service.create_game(
away_team_id=request.away_team_id,
home_team_id=request.home_team_id
)
return {"game_id": game.id, "status": "created"}
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
Service Integration
Routes use dependency injection to access services:
# Service dependencies from service_container.py
GameServiceDep = Annotated[GameService, Depends(get_game_service)]
UserServiceDep = Annotated[UserService, Depends(get_user_service)]
AuthServiceDep = Annotated[AuthService, Depends(get_auth_service)]
Route Organization
/auth - Authentication
GET /auth/login- Discord OAuth redirectGET /auth/callback- OAuth callback handlerPOST /auth/logout- Logout and session cleanup
/games - Game Management
POST /games/start- Create new gameGET /games/{game_id}- Get game detailsGET /games/- List active games
/api - HTMX JSON API
GET /api/scoreboard/{game_id}- Live scoreboard dataPOST /api/play- Execute gameplay action
/ - HTML Pages
GET /- Home pageGET /game/{game_id}- Game interface page
Error Handling
Routes should transform service exceptions to appropriate HTTP responses:
try:
result = await service.do_something()
return result
except NotFoundException as e:
raise HTTPException(status_code=404, detail=str(e))
except ValidationError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
logger.error(f"Unexpected error: {e}")
raise HTTPException(status_code=500, detail="Internal server error")
Testing Routes
Routes should be tested with service dependencies mocked:
from fastapi.testclient import TestClient
from unittest.mock import Mock
def test_start_game(mock_game_service):
client = TestClient(app)
# Mock service response
mock_game_service.create_game.return_value = Game(id=1)
response = client.post("/games/start", json={
"away_team_id": 1,
"home_team_id": 2
})
assert response.status_code == 200
assert response.json()["game_id"] == 1