Commit graph

9 commits

Author SHA1 Message Date
lila
ce19740cc8 fix(lint): resolve all eslint errors across monorepo
- Type response bodies in gameController.test.ts to fix no-unsafe-member-access
- Replace async methods with Promise.resolve() in InMemoryGameSessionStore
  and InMemoryLobbyGameStore to satisfy require-await rule
- Add argsIgnorePattern and varsIgnorePattern to eslint config so
  underscore-prefixed params are globally ignored
- Fix no-misused-promises in ws/index.ts, lobbyHandlers, gameHandlers,
  __root.tsx, login.tsx and play.tsx by using void + .catch()
- Fix no-floating-promises on navigate calls in login.tsx
- Move API_URL outside Play component to fix useCallback dependency warning
- Type fetch response bodies in play.tsx to fix no-unsafe-assignment
- Add only-throw-error: off for route files (TanStack Router throw redirect)
- Remove unused WebSocket import from express.d.ts
- Fix unsafe return in connections.ts by typing empty Map constructor
- Exclude scripts/ folder from eslint
- Add targeted override for better-auth auth-client.ts (upstream typing issue)
2026-04-17 16:46:33 +02:00
lila
4d1ebe2450 feat(api): add REST endpoints for lobby create and join
- POST /api/v1/lobbies creates a lobby with a Crockford-Base32
  6-char code, retrying on unique violation up to 5 times
- POST /api/v1/lobbies/:code/join validates lobby state then
  calls the model's atomic addPlayer, idempotent for repeat
  joins from the same user
- Routes require authentication via requireAuth
2026-04-16 19:51:38 +02:00
lila
3f7bc4111e chore: rename project from glossa to lila
- Update all package names from @glossa/* to @lila/*
- Update all imports, container names, volume names
- Update documentation references
- Recreate database with new credentials
2026-04-13 10:00:52 +02:00
lila
e320f43d8e test(api): add unit and integration tests for game service and endpoints
- Unit tests for createGameSession and evaluateAnswer (14 tests)
- Endpoint tests for POST /game/start and /game/answer via supertest (8 tests)
- Mock @glossa/db — no real database dependency
2026-04-12 09:04:41 +02:00
lila
48457936e8 feat(api): add global error handler with typed error classes
- Add AppError base class, ValidationError (400), NotFoundError (404)
- Add central error middleware in app.ts
- Remove inline safeParse error handling from controllers
- Replace plain Error throws with NotFoundError in gameService
2026-04-12 08:48:43 +02:00
lila
075a691849 feat(api): add answer evaluation endpoint
Complete the game answer flow:

- Add evaluateAnswer service function: looks up the session in the
  GameSessionStore, compares the submitted optionId against the stored
  correct answer, returns an AnswerResult.
- Add submitAnswer controller with safeParse validation and error
  handling (session/question not found → 404).
- Add POST /api/v1/game/answer route.
- Fix createGameSession: was missing the answerKey tracking and the
  gameSessionStore.create() call, so sessions were never persisted.

The full singleplayer game loop now works end-to-end:
POST /game/start → GameSession, POST /game/answer → AnswerResult.
2026-04-11 12:12:54 +02:00
lila
f53ac618bb feat(api): assemble full GameSession with shuffled answer options
Extend the game flow from raw term rows to a complete GameSession
matching the shared schema:

- Add getDistractors model query: fetches N same-POS, same-difficulty,
  same-target-language terms excluding a given termId. Returns bare
  strings since distractors only need their display text.
- Fix getGameTerms select clause to use the neutral field names
  (sourceText, targetText, sourceGloss) that the type already declared.
- Rename gameService entry point to createGameSession; signature now
  takes a GameRequest and returns a GameSession.
- Per question: fetch 3 distractors, combine with the correct answer,
  shuffle (Fisher-Yates), assign optionIds 0-3 by post-shuffle index,
  and assemble into a GameQuestion with a fresh UUID.
- Wrap the questions in a GameSession with its own UUID.
- Run per-question distractor fetches in parallel via Promise.all.

Known gap: the correct option is not yet remembered server-side, so
/game/answer cannot evaluate submissions. SessionStore lands next.
2026-04-10 21:44:36 +02:00
lila
9fc3ba375a feat: scaffold quiz API vertical slice
- Add GameRequestSchema and derived types to packages/shared
- Add SupportedLanguageCode, SupportedPos, DifficultyLevel type exports
- Add getGameTerms() model to packages/db with pos/language/difficulty/limit filters
- Add prepareGameQuestions() service skeleton in apps/api
- Add createGame controller with Zod safeParse validation
- Wire POST /api/v1/game/start route
- Add scripts/gametest/test-game.ts for manual end-to-end testing
2026-04-09 13:47:01 +02:00
lila
7d80b20390 wip version of the api 2026-04-05 00:33:34 +02:00