3 Commits
Author SHA1 Message Date
tiennm99 4d25a82448 chore(ci): raise the test hook timeout, fail an empty backup
PGlite start-up alone takes about seven seconds on an ARM host, so the
10s beforeAll default failed whole files at random. The weekly backup
fails instead of uploading an empty export, and both workflows run with
read-only permissions; CI cancels superseded runs.
2026-09-28 15:01:41 +07:00
tiennm99 6569f095c9 feat(game): serve panorama index from Neon Postgres
- panoramas + pano_provinces tables replace 28MB bundled JSON; pano-index.js
  now draws via cached COUNT + ORDER BY id OFFSET with rejection sampling,
  composite (province,id)/(district,id) indexes support the skip
- scripts/seed-pano-db.mjs validates pipeline artifacts (the old real-data
  vitest invariants, extracted to scripts/lib/pano-artifacts.mjs), stages
  into panoramas_next, verifies, renames into place in one transaction,
  keeps panoramas_old as backup; --province reseeds in place; --check
  validates only
- pipeline writes gitignored data-build/panos/; pano barrel removed
- tests run against PGlite mocked in at the @neondatabase/serverless
  boundary, mirroring the fake-upstash pattern; fixtures replace real data
- infrastructure errors rethrow instead of reading as missing coverage;
  session ids via crypto.randomUUID (uuid package dropped)
2026-08-31 09:44:03 +07:00
tiennm99 c2c1ced387 test: cover the lib layer against a fake and a real Redis
Scoring, the Upstash key adapter, sessions and the leaderboards had no
coverage, and they carry the anti-cheat model: server-held coordinates,
session TTLs, rank arithmetic.

One suite runs against two backing stores. By default @upstash/redis is
mocked with an in-memory fake, so `npm test` needs no service and
finishes well under a second. With TEST_REDIS=real the mock steps aside
and the same files run against a real Redis behind SRH, the proxy
Upstash recommends for local work, since the SDK speaks HTTP REST rather
than RESP and a plain Redis container cannot serve it alone.

Running both is what keeps the fake honest: a semantic it gets wrong
shows up as a green unit run and a red integration run. Two tests skip
against real Redis, one asserting a response shape only an older SDK
produces and one fast-forwarding half an hour to watch a session expire.

The suite was checked by mutation rather than by passing alone. Breaking
a score band, the key prefix and the session TTL each failed a test;
reversing the global trim window did not, because only the city
leaderboard was asserted, so that test now covers both scopes.

The compose stack doubles as a local Redis for `npm run dev`, which had
no credentials to reach one before.

package.json also loses the eight unused runtime dependencies removed in
the cleanup that follows; they cannot be split from the same file.
2026-08-30 09:26:02 +07:00