paper-dynasty-gameplay-webapp/app/routers
Cal Corum c09f9d1302 CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture
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>
2025-09-27 21:44:12 -05:00
..
__init__.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
api.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
auth.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
games.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
pages.py CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00
README.md CLAUDE: Initialize Paper Dynasty web app with Model/Service Architecture 2025-09-27 21:44:12 -05:00

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: AuthService for business logic

games.py

Game-related endpoints:

  • Game Creation: Start new games
  • Game Retrieval: Get game details and listings
  • Uses: GameService for business logic

api.py

JSON API endpoints for HTMX:

  • Live Updates: Scoreboard and game state
  • Player Actions: Execute gameplay actions
  • Uses: GameplayService for 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 redirect
  • GET /auth/callback - OAuth callback handler
  • POST /auth/logout - Logout and session cleanup

/games - Game Management

  • POST /games/start - Create new game
  • GET /games/{game_id} - Get game details
  • GET /games/ - List active games

/api - HTMX JSON API

  • GET /api/scoreboard/{game_id} - Live scoreboard data
  • POST /api/play - Execute gameplay action

/ - HTML Pages

  • GET / - Home page
  • GET /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