A Node.js/TypeScript backend API for a two-player dice game with authentication.
- Authentication: JWT-based authentication system
- Game Management: Create, manage, and play dice games
- Game Rules Enforcement: All game logic enforced on the backend
- State Management: Complete game state management
- 2 players play in rounds
- On a turn, a player rolls 2 dice as many times as they want
- Each roll adds to the round score
- If the player rolls 6 & 6, the round score is lost and the turn passes
- A player can Hold: the round score is added to the global score and the turn passes
- The first player to reach the winning score wins
- Players can set the winning score (default: 100)
- A player can start a new game at any time
- Install dependencies:
npm install- Create a
.envfile (copy from.env.example):
PORT=3000
JWT_SECRET=your-secret-key-change-this-in-production
NODE_ENV=development
DB_PATH=./data/dice-game.db # Optional: custom database path
- Build the project:
npm run build- Run the server:
npm startOr run in development mode with auto-reload:
npm run devThe application uses SQLite for persistent storage. The database file is automatically created in the data/ directory on first run.
- Database location:
./data/dice-game.db(or path specified inDB_PATHenv variable) - Auto-initialization: The database schema is automatically created on server start
- Persistence: All users and games are saved to disk and persist across server restarts
The database includes:
userstable: Stores user accounts with hashed passwordsgamestable: Stores all game states and progress
-
POST /api/auth/register- Register a new user- Body:
{ "username": "string", "password": "string" } - Returns:
{ "token": "string", "user": { "id": "string", "username": "string" } }
- Body:
-
POST /api/auth/login- Login- Body:
{ "username": "string", "password": "string" } - Returns:
{ "token": "string", "user": { "id": "string", "username": "string" } }
- Body:
-
GET /api/auth/me- Get current user (requires authentication)- Headers:
Authorization: Bearer <token> - Returns:
{ "id": "string", "username": "string" }
- Headers:
All game endpoints require authentication (Bearer token in Authorization header).
-
POST /api/games- Create a new game- Body:
{ "player1Username": "string", "player2Username": "string", "winningScore": number (optional, default: 100) } - Returns: Game state object
- Body:
-
GET /api/games/my-games- Get all games for the authenticated user- Returns: Array of game state objects
-
GET /api/games/:gameId- Get a specific game- Returns: Game state object
-
POST /api/games/:gameId/roll- Roll the dice- Returns:
{ "dice": { "die1": number, "die2": number, "timestamp": number }, "roundScore": number, "isDoubleSix": boolean, "gameState": GameState }
- Returns:
-
POST /api/games/:gameId/hold- Hold and pass turn- Returns:
{ "gameState": GameState, "isGameOver": boolean, "winnerId": "string" (optional) }
- Returns:
-
POST /api/games/:gameId/new-game- Start a new game (reset current game)- Body:
{ "winningScore": number (optional) } - Returns: Game state object
- Body:
-
POST /api/games/:gameId/end- End the game and determine winner- Returns: Game state object with status 'finished' and winnerId set
- Determines winner based on current scores (higher score wins, or current player if tied)
-
DELETE /api/games/:gameId- Delete a game- Returns:
{ "message": "Game deleted successfully" }
- Returns:
{
id: string;
player1: { id: string, userId: string, username: string };
player2: { id: string, userId: string, username: string };
currentPlayerId: string;
player1Score: number;
player2Score: number;
player1RoundScore: number;
player2RoundScore: number;
winningScore: number;
status: 'waiting' | 'active' | 'finished';
winnerId?: string;
createdAt: number;
updatedAt: number;
}- Type checking:
npm run type-check - Build:
npm run build - Dev mode:
npm run dev