mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-09 15:11:29 -07:00
[leaderboard] add stub
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import type { HonoApp } from '@repo/hono-helpers'
|
||||
import type { SharedHonoEnv, SharedHonoVariables } from '@repo/hono-helpers/src/types'
|
||||
|
||||
export type Env = SharedHonoEnv & {
|
||||
/**
|
||||
* Shared Secrets Store binding for the HS256 JWT signing key. Resolve the value with
|
||||
* `await env.JWT_SECRET.get()`; every worker binds the same store, so tokens signed by
|
||||
* `auth` verify here.
|
||||
*/
|
||||
JWT_SECRET: SecretsStoreSecret
|
||||
}
|
||||
|
||||
/** Variables can be extended */
|
||||
export type Variables = SharedHonoVariables
|
||||
|
||||
export interface App extends HonoApp {
|
||||
Bindings: Env
|
||||
Variables: Variables
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Hono } from 'hono'
|
||||
import { useWorkersLogger } from 'workers-tagged-logger'
|
||||
|
||||
import { logger, withNotFound, withOnError } from '@repo/hono-helpers'
|
||||
|
||||
import type { App } from './context'
|
||||
|
||||
/**
|
||||
* Leaderboard Worker. Nothing scores anything here yet — the one route answers the shape
|
||||
* the client parses, with no rows in it.
|
||||
*/
|
||||
const app = new Hono<App>()
|
||||
.use(
|
||||
'*',
|
||||
// middleware
|
||||
(c, next) =>
|
||||
useWorkersLogger(c.env.NAME, {
|
||||
environment: c.env.ENVIRONMENT,
|
||||
release: c.env.SENTRY_RELEASE,
|
||||
})(c, next)
|
||||
)
|
||||
|
||||
.onError(withOnError())
|
||||
.notFound(withNotFound())
|
||||
|
||||
.get('/', async (c) => {
|
||||
return c.text('hello, world!')
|
||||
})
|
||||
|
||||
// The scores around a player — what the client shows when it opens a leaderboard on
|
||||
// someone rather than at the top. Answers `{ Rows: [...] }`; an EMPTY `Rows` is a
|
||||
// complete answer meaning "this leaderboard has no scores", which the client renders as
|
||||
// a blank board instead of failing. The key must be present — a bare `{}` trips its
|
||||
// parser.
|
||||
//
|
||||
// Nothing is ranked or stored yet, so the request body is ignored. It IS logged: the
|
||||
// body's shape hasn't been recovered from the client, and this route is how it gets
|
||||
// watched. Read it as text — the shape is unknown, so parsing it would only invent one —
|
||||
// and never fail on it, since an unreadable body must not cost the client its board.
|
||||
.post('/leaderboard/GetNearbyScores', async (c) => {
|
||||
const body = await c.req.text().catch(() => '<unreadable>')
|
||||
logger.info('GetNearbyScores', { body })
|
||||
|
||||
const rows: unknown[] = []
|
||||
return c.json({ Rows: rows })
|
||||
})
|
||||
|
||||
export default app
|
||||
@@ -0,0 +1,17 @@
|
||||
import { SELF } from 'cloudflare:test'
|
||||
import { expect, it } from 'vitest'
|
||||
|
||||
it('response with hello world', async () => {
|
||||
const res = await SELF.fetch('https://example.com')
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.text()).toMatchInlineSnapshot(`"hello, world!"`)
|
||||
})
|
||||
|
||||
it('answers GetNearbyScores with an empty row list', async () => {
|
||||
const res = await SELF.fetch('https://example.com/leaderboard/GetNearbyScores', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toEqual({ Rows: [] })
|
||||
})
|
||||
Reference in New Issue
Block a user