Commit Graph

487 Commits

Author SHA1 Message Date
85e3fb60f6 feat(backend): add game history API and live game previews
- GET /games/me/active and /games/me (Bearer token), /games/popular (live
  games, or the most spectated finished ones), and /game/:id now also
  returns saved records of finished games
- Lists are cached in Valkey for 10 seconds, cleared when a game is saved,
  and empty instead of failing while the database is down
- Live game previews over WebSocket: subscribers get the top 5 on
  subscribe and on change, at most once per second, without counting as
  spectators; ids are public ids
- RTMT supports several connection listeners
2026-10-16 00:21:09 +03:00
7239bbb6ed feat(backend): save every game and keep live games across restarts
- Games record start and move times, spectator peak and distinct count
- Games end as completed, left (the leaver loses), timeout (5 minutes
  offline on your turn while the opponent is online) or inactive (both
  offline for 30 minutes); everyone gets on_game_end
- Connection info carries offlineSince for the countdown
- A new game is rejected while the user has one in progress
- Live games are written to Valkey after every change and restored on
  startup; finished games are saved to Postgres with public ids, and
  saves that fail are kept and retried every 30 seconds
- Clients get a trimmed game without spectator ids
- Startup waits for Valkey, restores games, then accepts connections;
  migrations are retried while Postgres is unreachable
2026-10-16 00:18:33 +03:00
f6136be007 feat(backend): keep live games and caches in Valkey
- Valkey client that fails commands at once while Valkey is down instead
  of queueing them, and logs connection errors once
- ValkeyLiveGameStore: live game snapshots and finished games waiting to
  be saved, loaded with SCAN on startup
- ValkeyCache: JSON values with a TTL; errors count as cache misses
- Integration tests against a real Valkey, including an unreachable one
2026-10-16 00:14:07 +03:00
f404b92aaf feat(backend): save finished games in Postgres
- Connection pool and a small migration runner (schema_migrations, one
  transaction per migration, advisory lock)
- games and game_players tables with indexes for a user's games and for
  popular games
- PostgresGameHistoryRepository: idempotent save, get, recent games of a
  user, popular games
- Integration tests against a real Postgres via testcontainers; a custom
  Jest environment gives tests Node's web globals, which Jest 27 leaves out
- GameRecord carries the number of distinct spectators
2026-10-16 00:11:12 +03:00
ed2a909f16 fix(backend): clean up spectators and finished games
- Spectators are removed from games when they disconnect; the lookup
  iterated an iterator with for...in and never found anything
- Finished and left games are removed from memory, not only from the
  player mappings
- The connection info is sent once when a game starts
2026-10-16 00:08:38 +03:00
16026fb6cb feat(core): add game history types and move history helpers
- PlayerSummary, MoveRecord, live and finished game summaries, GameRecord,
  timeout constants, startedAt/moveTimes on Game and offlineSince on
  UserConnectionInfo
- Channels for live game previews and for rejecting a new game while one
  is in progress
- getInitialBoard, getBoardAfterMove, describeMove and createGameAtMove,
  with tests against games played with the engine
- English and Turkish strings for the new screens
2026-10-16 00:07:36 +03:00
29fa443b93 build: add shared Postgres and Valkey to compose
- postgres replaces keycloak-db and holds a keycloak and a mancala database,
  each with its own user, created by apps/postgres/init
- valkey with an append-only file for live game state and caches
- backend gets DATABASE_URL and VALKEY_URL
2026-10-16 00:05:21 +03:00
d0004742f5 docs: add game history and live games spec 2026-10-16 00:03:32 +03:00
20efa40e6c docs: add TODO with mobile login and open issues 2026-10-14 09:13:52 +03:00
f5dcf930fa feat(frontend): log in with Keycloak, as a guest or with an account
- First visit logs in as a new guest through Keycloak without a form;
  the session, including an offline refresh token, is kept in local storage
- Account menu on the home page: guests can log in or sign up, users can
  log out (which starts a new guest session)
- The WebSocket client in core authenticates with the access token after
  connecting, reports "connected" once the server accepts it, and re-sends
  renewed tokens on the open connection
- Game page shows player names; guests appear as "Guest 4F2A"
- Auth channels, AuthUser and player names in UserConnectionInfo move to
  core and the backend uses them from there
- Mobile keeps using userKey login for now
2026-10-14 02:22:13 +03:00
e165b0a0eb build: use local mancala.js and @mancala/core packages
- Apps and @mancala/core depend on the packages in this repo through
  link: dependencies instead of the npm releases, so changes no longer
  need a publish
- Root package.json gets a build:packages script that installs and
  builds both packages
- Backend and frontend Docker images are built from the repo root so
  they can include the packages; compose builds them that way
- Metro watches the packages folder and resolves their imports from the
  app's node_modules
2026-10-14 02:09:05 +03:00
30ad51c493 feat(backend): authenticate WebSocket clients with Keycloak tokens
- New auth module verifies Keycloak access tokens offline against the
  realm's signing keys (issuer, RS256, typ=Bearer, allowed azp); guests
  are recognised by the guest realm role
- Clients send an auth message after connecting and get on_auth or
  on_auth_error; unauthenticated sockets are closed after 5 seconds and
  their messages ignored; a socket can refresh its token but not switch user
- A user can be connected from several sockets; a late close of an old
  socket no longer drops the new one
- Malformed messages are ignored instead of throwing
- Games store player names and guest flags and send them with the
  connection info
- Legacy ?userKey= clients and /register stay available behind
  LEGACY_USERKEY_AUTH; legacy keys must be UUIDs so they cannot take a
  Keycloak user's kc: id
- TypeScript target raised to es2020 for async/await
2026-10-14 01:52:07 +03:00
7c99a76af7 feat(keycloak): add Keycloak with guest login extension
- Custom authenticator creates and logs in a guest user when the
  authorization request has guest=true; other requests get the login form
- Scheduled task removes guests with no remaining sessions
- Realm export with mancala-web PKCE client, guest role and guest-aware
  browser flow (verify profile disabled so guests are not asked for details)
- Dockerfile building the extension into a Keycloak 26.7.5 image
- Keycloak and Postgres in compose; nginx proxies auth.playmancala.app
  and rate limits the auth endpoint
- Integration tests run the extension and realm in a Keycloak container
2026-10-14 01:46:48 +03:00
69664796ce feat(mobile): implement "Rejoin Game" functionality and fix storage bugs 2026-07-16 02:00:25 +03:00
8a485e2db3 Merge pull request 'fix/stone-count-text' (#2) from fix/stone-count-text into main
Reviewed-on: #2
2026-07-04 11:55:32 +03:00
0be96a6229 fix: display stone count immediately on board pits 2026-07-04 11:54:31 +03:00
3efc7c5ffe fix(mobile): fix android build issue 2026-07-02 23:44:55 +03:00
0618527ac7 Merge pull request 'feature/stone-count-text' (#1) from feature/stone-count-text into main
Reviewed-on: #1
2026-07-02 21:12:44 +03:00
9c95d9dc44 feat(mobile): display stone count in pit 2026-05-26 00:32:20 +03:00
ca92b20b59 feat(frontend): display stone count in pit 2026-05-26 00:31:59 +03:00
bb1c750080 feat(mobile): upgrade react native version
chore(mobile): update version to 0.5.0
2025-11-17 00:25:41 +03:00
8457fbfd66 add nginx config 2024-12-22 03:29:06 +03:00
230dd0ecff chore(frontend): upgrade uuid version 2024-12-22 02:02:44 +03:00
3f5db4be22 fix(frontend): update websocket server default address 2024-12-22 00:55:20 +03:00
47f56b8bda update compose.yaml 2024-12-22 00:49:30 +03:00
6d59c33300 [ci] trigger test1 2024-12-21 22:25:47 +03:00
9c42f867e9 v0.4.7 2024-12-08 23:26:17 +03:00
72aa95ca97 fix(mobile): update server address 2024-12-08 23:25:45 +03:00
5d4ce2799c fix(frontend): env variable 2024-12-08 23:24:22 +03:00
0c96056f84 v0.4.6 2024-12-08 22:49:21 +03:00
313dd3d549 feat: add docker compose 2024-12-08 22:47:30 +03:00
9dedc31626 fea(frontend): add WS_SERVER_ADDRESS env 2024-12-08 22:47:02 +03:00
c916eef54e remove github action 2024-10-05 19:33:46 +03:00
734417b0a6 (frontend) add docker file 2024-10-04 23:31:55 +03:00
7860f9aac4 (refactor) change folder structure 2024-06-18 01:11:26 +03:00
7d407db1ef (frontend) fix current lang 2024-06-18 01:02:29 +03:00
340fde01a1 [backend] fix github action 2024-06-18 00:48:44 +03:00
fbfc439e04 v0.4.5 2024-06-18 00:42:40 +03:00
61f154c90d [core] v0.0.2 2024-06-18 00:41:31 +03:00
e198e0fdcf (refactor) move http service to core package 2024-06-18 00:36:35 +03:00
bef8f1d9e9 (refactor) move pit animatorto core package 2024-06-18 00:24:45 +03:00
3c1c61fc7d (refactor) move ColorUtil to core package 2024-06-18 00:02:52 +03:00
66b61215c1 (refactor) add i18n to frontend and refactor 2024-06-17 23:50:13 +03:00
02277287d0 (refactor) upgrade ts version 2024-06-17 23:48:51 +03:00
3e321416d9 [refactor] move theme to core package 2024-06-17 18:52:26 +03:00
f371414f98 [refactor]: move rtmt to core package 2024-06-17 18:20:06 +03:00
597bb708f1 [refactor] move models to core package 2024-06-17 15:37:17 +03:00
6c2b15070d [chore] move .gitignore file to mobile folder 2024-06-17 12:26:19 +03:00
aa66d2fb22 [backend] fix github actions 2024-06-17 00:36:59 +03:00
67d5c787c1 [backend] fix github actions 2024-06-17 00:33:51 +03:00