WIP: feat: NCS-38 Http4s server #26

Closed
lq64 wants to merge 2 commits from feat/NCS-38 into main
Owner

IMPORTANT NOTE: DO NOT MERGE THIS PR AS STATED IN THE TICKET DESCRIPTION.

This code is not covered by the tests because this will not go into production.

Added http4s server according to the API specification. A game is playable via API.

Summary

  • Adds a new server module implementing the OpenAPI spec from docs/api-spec.yaml
  • Uses Http4s 0.23 (Ember) + Circe 0.14 for routing and JSON serialization
  • Server runs standalone via ./gradlew :modules:server:run on 0.0.0.0:8080

Endpoints

All routes are under /api/board/game/... following the lichess board/bot split convention, reserving
/api/bot/game/... for a future bot API.

  • Game lifecycle: create, get, stream (snapshot), resign
  • Move-making: POST /{id}/move/{uci}, legal moves, undo, redo
  • Draw handling: offer, accept, decline, claim
  • Import: FEN, PGN
  • Export: FEN, PGN

Architecture

  • GameRegistry — thread-safe in-memory game store (Ref[IO, Map[String, GameEntry]])
  • GameEntry — wraps GameEngine with an internal Observer that captures terminal state (checkmate, stalemate,
    draw) before the engine resets its context
  • BoardRoutes — single HttpRoutes.of[IO] block, each case delegates to a private handler
  • ServerAppIOApp entry point; ServerLauncher not included (kept separate from ui to avoid cross-module
    IOApp resolution issues with Scala 3)
  • Coverage exempt (infrastructure entrypoint, same policy as ui)

Test plan

  • ./compile passes clean
  • ./gradlew :modules:server:run starts without errors
  • POST /api/board/game returns a GameFullDto with a fresh game
  • POST /api/board/game/{id}/move/e2e4 returns updated state with turn: "black"
  • GET /api/board/game/{id}/moves?square=e4 returns legal moves from e4
  • POST /api/board/game/import/fen with a valid FEN returns a new game
  • GET /api/board/game/{id}/export/pgn returns PGN text
  • POST /api/board/game/{id}/resign returns {"ok": true}
  • Unknown game ID returns 404 with GAME_NOT_FOUND error code
  • Illegal move returns 400 with INVALID_MOVE error code
IMPORTANT NOTE: DO NOT MERGE THIS PR AS STATED IN THE TICKET DESCRIPTION. This code is not covered by the tests because this will not go into production. Added http4s server according to the API specification. A game is playable via API. ## Summary - Adds a new `server` module implementing the OpenAPI spec from `docs/api-spec.yaml` - Uses Http4s 0.23 (Ember) + Circe 0.14 for routing and JSON serialization - Server runs standalone via `./gradlew :modules:server:run` on `0.0.0.0:8080` ## Endpoints All routes are under `/api/board/game/...` following the lichess board/bot split convention, reserving `/api/bot/game/...` for a future bot API. - Game lifecycle: create, get, stream (snapshot), resign - Move-making: `POST /{id}/move/{uci}`, legal moves, undo, redo - Draw handling: offer, accept, decline, claim - Import: FEN, PGN - Export: FEN, PGN ## Architecture - `GameRegistry` — thread-safe in-memory game store (`Ref[IO, Map[String, GameEntry]]`) - `GameEntry` — wraps `GameEngine` with an internal `Observer` that captures terminal state (checkmate, stalemate, draw) before the engine resets its context - `BoardRoutes` — single `HttpRoutes.of[IO]` block, each case delegates to a private handler - `ServerApp` — `IOApp` entry point; `ServerLauncher` not included (kept separate from `ui` to avoid cross-module `IOApp` resolution issues with Scala 3) - Coverage exempt (infrastructure entrypoint, same policy as `ui`) ## Test plan - [ ] `./compile` passes clean - [ ] `./gradlew :modules:server:run` starts without errors - [ ] `POST /api/board/game` returns a `GameFullDto` with a fresh game - [ ] `POST /api/board/game/{id}/move/e2e4` returns updated state with `turn: "black"` - [ ] `GET /api/board/game/{id}/moves?square=e4` returns legal moves from e4 - [ ] `POST /api/board/game/import/fen` with a valid FEN returns a new game - [ ] `GET /api/board/game/{id}/export/pgn` returns PGN text - [ ] `POST /api/board/game/{id}/resign` returns `{"ok": true}` - [ ] Unknown game ID returns `404` with `GAME_NOT_FOUND` error code - [ ] Illegal move returns `400` with `INVALID_MOVE` error code
lq64 added 1 commit 2026-04-12 18:16:53 +02:00
feat(server): Http4s server
Build & Test (NowChessSystems) TeamCity build failed
25c113e4d5
Added http4s server according to the API specification. A game is playable via API
lq64 added 1 commit 2026-04-12 18:50:53 +02:00
feat(server): Http4s server
Build & Test (NowChessSystems) TeamCity build failed
df675a5f08
Changed at how the run command starts TUI GUI and the server. This is neccessary so that TUI GUI and server start and the game from the TUI/GUI is registered in the server.
Janis closed this pull request 2026-04-17 21:56:15 +02:00
Some checks are pending
Build & Test (NowChessSystems) TeamCity build failed

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: NowChess/NowChessSystems#26