mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-09 15:11:29 -07:00
update some naming conventions
This commit is contained in:
+3
-2
@@ -5,7 +5,8 @@ RECFLARE_DOMAIN=rec.example.com
|
|||||||
# worker's directory name. Defaults to the directory name when unset.
|
# worker's directory name. Defaults to the directory name when unset.
|
||||||
# RECFLARE_SUBDOMAINS={"playersettings":"settings"}
|
# RECFLARE_SUBDOMAINS={"playersettings":"settings"}
|
||||||
|
|
||||||
# D1 database ids, as a compact JSON object keyed by the worker's directory name.
|
# Id of the shared `recflare` D1 database (create it manually with
|
||||||
|
# `wrangler d1 create recflare`). All D1-backed workers bind this one database.
|
||||||
# Kept out of the committed wrangler.jsonc (which uses a "local" placeholder) and
|
# Kept out of the committed wrangler.jsonc (which uses a "local" placeholder) and
|
||||||
# spliced in at deploy time. Required to deploy any worker that uses D1.
|
# spliced in at deploy time. Required to deploy any worker that uses D1.
|
||||||
# RECFLARE_D1={"rooms":"d44083e1-5bfe-4467-aa9a-f13c5c2496d5"}
|
# RECFLARE_D1=d44083e1-5bfe-4467-aa9a-f13c5c2496d5
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Account storage on the shared `rec-rooms` D1 database. Each account is a single
|
* Account storage on the shared `recflare` D1 database. Each account is a single
|
||||||
* JSON blob in the `data` column; queryable fields (AccountId, Username) are
|
* JSON blob in the `data` column; queryable fields (AccountId, Username) are
|
||||||
* SQLite generated (virtual) columns extracted from that JSON and indexed —
|
* SQLite generated (virtual) columns extracted from that JSON and indexed —
|
||||||
* the same JSON-blob pattern the `rooms` worker uses.
|
* the same JSON-blob pattern the `rooms` worker uses.
|
||||||
|
|||||||
@@ -4,13 +4,15 @@
|
|||||||
"main": "src/accounts.app.ts",
|
"main": "src/accounts.app.ts",
|
||||||
"compatibility_date": "2025-09-20",
|
"compatibility_date": "2025-09-20",
|
||||||
"compatibility_flags": ["nodejs_compat"],
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
// Shared D1 database. The `accounts` table schema/migrations are owned by the
|
// Shared `recflare` D1 database. The `accounts` table schema/migrations are owned
|
||||||
// `auth` worker; this worker binds it read/write to look up and create accounts.
|
// by the `auth` worker; this worker binds it read/write to look up and create
|
||||||
|
// accounts. The "local" placeholder is replaced with the real id from RECFLARE_D1
|
||||||
|
// (see .env) at deploy time.
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "rec-rooms",
|
"database_name": "recflare",
|
||||||
"database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5"
|
"database_id": "local"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"logpush": false,
|
"logpush": false,
|
||||||
|
|||||||
@@ -518,7 +518,7 @@ const app = new Hono<App>({ strict: false })
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ---- Room server ----------------------------------------------------------
|
// ---- Room server ----------------------------------------------------------
|
||||||
// Room data is read from the shared `rec-rooms` D1 (owned by the rooms worker).
|
// Room data is read from the shared `recflare` D1 (owned by the rooms worker).
|
||||||
// Register specific paths before the `/:id` param route.
|
// Register specific paths before the `/:id` param route.
|
||||||
.get('/roomserver/rooms/bulk', async (c) => {
|
.get('/roomserver/rooms/bulk', async (c) => {
|
||||||
const idParam = c.req.query('id')
|
const idParam = c.req.query('id')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Read helpers for the shared `rec-rooms` D1 database. The schema, migrations,
|
* Read helpers for the shared `recflare` D1 database. The schema, migrations,
|
||||||
* and seed are owned by the `rooms` worker (apps/rooms/src/rooms-db.ts +
|
* and seed are owned by the `rooms` worker (apps/rooms/src/rooms-db.ts +
|
||||||
* migrations); this worker binds the same database read-only for its
|
* migrations); this worker binds the same database read-only for its
|
||||||
* `/roomserver/rooms/*` endpoints. Keep these queries in sync with the rooms
|
* `/roomserver/rooms/*` endpoints. Keep these queries in sync with the rooms
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ declare module 'cloudflare:test' {
|
|||||||
|
|
||||||
const ORIGIN = 'https://example.com'
|
const ORIGIN = 'https://example.com'
|
||||||
|
|
||||||
// The /roomserver/rooms/* routes read from the shared rec-rooms D1. Set up the
|
// The /roomserver/rooms/* routes read from the shared recflare D1. Set up the
|
||||||
// schema (matching the rooms worker's migration) + a couple of rooms for tests.
|
// schema (matching the rooms worker's migration) + a couple of rooms for tests.
|
||||||
const TEST_ROOMS = [
|
const TEST_ROOMS = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
"main": "src/api.app.ts",
|
"main": "src/api.app.ts",
|
||||||
"compatibility_date": "2025-09-20",
|
"compatibility_date": "2025-09-20",
|
||||||
"compatibility_flags": ["nodejs_compat"],
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
// Shared rooms DB (created + migrated by the `rooms` worker; bound read-only here).
|
// Shared `recflare` DB (bound read-only here). Created manually with
|
||||||
|
// `wrangler d1 create recflare`; its id lives in RECFLARE_D1 (see .env) and the
|
||||||
|
// "local" placeholder below is spliced out at deploy time.
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "rec-rooms",
|
"database_name": "recflare",
|
||||||
"database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5"
|
"database_id": "local"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// Image bucket shared with the `img` worker (which serves objects back by key).
|
// Image bucket shared with the `img` worker (which serves objects back by key).
|
||||||
@@ -17,7 +19,7 @@
|
|||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
{
|
{
|
||||||
"binding": "IMAGES",
|
"binding": "IMAGES",
|
||||||
"bucket_name": "rec-img"
|
"bucket_name": "recflare-img"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"logpush": false,
|
"logpush": false,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Account storage on the shared `rec-rooms` D1 database. Each account is a single
|
* Account storage on the shared `recflare` D1 database. Each account is a single
|
||||||
* JSON blob in the `data` column; queryable fields (AccountId, Username) are
|
* JSON blob in the `data` column; queryable fields (AccountId, Username) are
|
||||||
* SQLite generated (virtual) columns extracted from that JSON and indexed —
|
* SQLite generated (virtual) columns extracted from that JSON and indexed —
|
||||||
* the same JSON-blob pattern the `rooms` worker uses.
|
* the same JSON-blob pattern the `rooms` worker uses.
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ async function placeNewPlayerInOrientation(env: App['Bindings'], accountId: numb
|
|||||||
platform: 0,
|
platform: 0,
|
||||||
appVersion: '20230302',
|
appVersion: '20230302',
|
||||||
}
|
}
|
||||||
await env.MATCH_PRESENCE.put(`presence:${accountId}`, JSON.stringify(presence), {
|
await env.RECFLARE_MATCH_PRESENCE.put(`presence:${accountId}`, JSON.stringify(presence), {
|
||||||
expirationTtl: PRESENCE_TTL,
|
expirationTtl: PRESENCE_TTL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export type Env = SharedHonoEnv & {
|
|||||||
// Shared match-presence KV (owned by the `match` worker). On account creation
|
// Shared match-presence KV (owned by the `match` worker). On account creation
|
||||||
// the new player's presence is seeded to the Orientation room so the match
|
// the new player's presence is seeded to the Orientation room so the match
|
||||||
// heartbeat keeps them there instead of bouncing them to the dorm.
|
// heartbeat keeps them there instead of bouncing them to the dorm.
|
||||||
MATCH_PRESENCE: KVNamespace
|
RECFLARE_MATCH_PRESENCE: KVNamespace
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Variables can be extended */
|
/** Variables can be extended */
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ describe('auth worker routes', () => {
|
|||||||
test('POST /connect/token create_account seeds the new player into Orientation', async () => {
|
test('POST /connect/token create_account seeds the new player into Orientation', async () => {
|
||||||
const payload = await tokenFor('grant_type=create_account&platform_id=steam-456')
|
const payload = await tokenFor('grant_type=create_account&platform_id=steam-456')
|
||||||
const sub = payload.sub as string
|
const sub = payload.sub as string
|
||||||
const presence = await env.MATCH_PRESENCE.get<{
|
const presence = await env.RECFLARE_MATCH_PRESENCE.get<{
|
||||||
roomInstance: { roomInstanceId: number; roomId: number; location: string; name: string }
|
roomInstance: { roomInstanceId: number; roomId: number; location: string; name: string }
|
||||||
}>(`presence:${sub}`, 'json')
|
}>(`presence:${sub}`, 'json')
|
||||||
expect(presence).not.toBeNull()
|
expect(presence).not.toBeNull()
|
||||||
|
|||||||
@@ -4,14 +4,16 @@
|
|||||||
"main": "src/auth.app.ts",
|
"main": "src/auth.app.ts",
|
||||||
"compatibility_date": "2025-09-20",
|
"compatibility_date": "2025-09-20",
|
||||||
"compatibility_flags": ["nodejs_compat"],
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
// Shared D1 database (also used by the rooms worker). The `auth` worker owns
|
// Shared `recflare` D1 database (also used by the rooms worker). The `auth` worker
|
||||||
// the `accounts` table; a dedicated migrations_table keeps its migration
|
// owns the `accounts` table; a dedicated migrations_table keeps its migration
|
||||||
// history separate from the rooms worker's migrations on the same database.
|
// history separate from the rooms worker's migrations on the same database. The
|
||||||
|
// "local" placeholder is replaced with the real id from RECFLARE_D1 (see .env) at
|
||||||
|
// deploy time.
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "rec-rooms",
|
"database_name": "recflare",
|
||||||
"database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5",
|
"database_id": "local",
|
||||||
"migrations_dir": "migrations",
|
"migrations_dir": "migrations",
|
||||||
"migrations_table": "d1_migrations_auth"
|
"migrations_table": "d1_migrations_auth"
|
||||||
}
|
}
|
||||||
@@ -20,7 +22,7 @@
|
|||||||
// accounts into the Orientation room on signup.
|
// accounts into the Orientation room on signup.
|
||||||
"kv_namespaces": [
|
"kv_namespaces": [
|
||||||
{
|
{
|
||||||
"binding": "MATCH_PRESENCE",
|
"binding": "RECFLARE_MATCH_PRESENCE",
|
||||||
"id": "9f53f04b7dd244658d59f515a14748b6"
|
"id": "9f53f04b7dd244658d59f515a14748b6"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
{
|
{
|
||||||
"binding": "CDN_ASSETS",
|
"binding": "CDN_ASSETS",
|
||||||
"bucket_name": "rec-cdn"
|
"bucket_name": "recflare-cdn"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"upload_source_maps": true,
|
"upload_source_maps": true,
|
||||||
|
|||||||
+3
-3
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Image-delivery worker served on the `img` subdomain.
|
Image-delivery worker served on the `img` subdomain.
|
||||||
|
|
||||||
Images are stored as objects in the **`rec-img` R2 bucket** and streamed back by
|
Images are stored as objects in the **`recflare-img` R2 bucket** and streamed back by
|
||||||
key:
|
key:
|
||||||
|
|
||||||
- `GET /` — service status `{ "service": "img", "status": "ok" }`.
|
- `GET /` — service status `{ "service": "img", "status": "ok" }`.
|
||||||
@@ -37,7 +37,7 @@ node -e "const{generateKeyPairSync}=require('crypto');const{publicKey,privateKey
|
|||||||
## One-time bucket setup
|
## One-time bucket setup
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wrangler r2 bucket create rec-img
|
wrangler r2 bucket create recflare-img
|
||||||
```
|
```
|
||||||
|
|
||||||
## Seeding / uploading images
|
## Seeding / uploading images
|
||||||
@@ -45,7 +45,7 @@ wrangler r2 bucket create rec-img
|
|||||||
A starter image lives in `static/` so it can be uploaded to R2:
|
A starter image lives in `static/` so it can be uploaded to R2:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wrangler r2 object put rec-img/DefaultProfileImage.jpg \
|
wrangler r2 object put recflare-img/DefaultProfileImage.jpg \
|
||||||
--file=apps/img/static/DefaultProfileImage.jpg \
|
--file=apps/img/static/DefaultProfileImage.jpg \
|
||||||
--content-type=image/jpeg --remote
|
--content-type=image/jpeg --remote
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"r2_buckets": [
|
"r2_buckets": [
|
||||||
{
|
{
|
||||||
"binding": "IMAGES",
|
"binding": "IMAGES",
|
||||||
"bucket_name": "rec-img"
|
"bucket_name": "recflare-img"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"upload_source_maps": true,
|
"upload_source_maps": true,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export type Env = SharedHonoEnv & {
|
|||||||
// Per-player presence (the room instance they're currently in). Written by
|
// Per-player presence (the room instance they're currently in). Written by
|
||||||
// matchmake/goto, read by the heartbeat, cleared on login — mirrors the
|
// matchmake/goto, read by the heartbeat, cleared on login — mirrors the
|
||||||
// reference server's HeartbeatDB.
|
// reference server's HeartbeatDB.
|
||||||
MATCH_PRESENCE: KVNamespace
|
RECFLARE_MATCH_PRESENCE: KVNamespace
|
||||||
// Shared rooms DB (owned by the `rooms` worker). Read-only here to resolve a
|
// Shared rooms DB (owned by the `rooms` worker). Read-only here to resolve a
|
||||||
// room's real scene/subroom when matchmaking into it.
|
// room's real scene/subroom when matchmaking into it.
|
||||||
DB: D1Database
|
DB: D1Database
|
||||||
|
|||||||
@@ -98,14 +98,14 @@ const presenceKey = (id: number) => `presence:${id}`
|
|||||||
|
|
||||||
/** Persist the player's presence (room instance + status), refreshing the TTL. */
|
/** Persist the player's presence (room instance + status), refreshing the TTL. */
|
||||||
async function setPresence(c: Context<App>, id: number, presence: Presence): Promise<void> {
|
async function setPresence(c: Context<App>, id: number, presence: Presence): Promise<void> {
|
||||||
await c.env.MATCH_PRESENCE.put(presenceKey(id), JSON.stringify(presence), {
|
await c.env.RECFLARE_MATCH_PRESENCE.put(presenceKey(id), JSON.stringify(presence), {
|
||||||
expirationTtl: PRESENCE_TTL,
|
expirationTtl: PRESENCE_TTL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read the player's stored presence, or null when they aren't in a room. */
|
/** Read the player's stored presence, or null when they aren't in a room. */
|
||||||
async function getPresence(c: Context<App>, id: number): Promise<Presence | null> {
|
async function getPresence(c: Context<App>, id: number): Promise<Presence | null> {
|
||||||
return c.env.MATCH_PRESENCE.get<Presence>(presenceKey(id), 'json')
|
return c.env.RECFLARE_MATCH_PRESENCE.get<Presence>(presenceKey(id), 'json')
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Store the room instance the player just matchmade into, preserving status. */
|
/** Store the room instance the player just matchmade into, preserving status. */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Read helpers for the shared `rec-rooms` D1 database. The schema, migrations,
|
* Read helpers for the shared `recflare` D1 database. The schema, migrations,
|
||||||
* and seed are owned by the `rooms` worker (apps/rooms/src/rooms-db.ts +
|
* and seed are owned by the `rooms` worker (apps/rooms/src/rooms-db.ts +
|
||||||
* migrations); this worker binds the same database read-only to resolve a room's
|
* migrations); this worker binds the same database read-only to resolve a room's
|
||||||
* real scene/subroom when building a matchmake instance. Keep these queries in
|
* real scene/subroom when building a matchmake instance. Keep these queries in
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ declare module 'cloudflare:test' {
|
|||||||
|
|
||||||
const ORIGIN = 'https://example.com'
|
const ORIGIN = 'https://example.com'
|
||||||
|
|
||||||
// Matchmaking into a room resolves its real scene from the shared rec-rooms D1.
|
// Matchmaking into a room resolves its real scene from the shared recflare D1.
|
||||||
// Seed the schema + a couple of rooms (matching the rooms worker's migration).
|
// Seed the schema + a couple of rooms (matching the rooms worker's migration).
|
||||||
const RECCENTER_SCENE = 'cbad71af-0831-44d8-b8ef-69edafa841f6'
|
const RECCENTER_SCENE = 'cbad71af-0831-44d8-b8ef-69edafa841f6'
|
||||||
const TEST_ROOMS = [
|
const TEST_ROOMS = [
|
||||||
|
|||||||
@@ -5,19 +5,20 @@
|
|||||||
"compatibility_date": "2025-09-20",
|
"compatibility_date": "2025-09-20",
|
||||||
"compatibility_flags": ["nodejs_compat"],
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
// Per-player presence store (room instance the player is currently in).
|
// Per-player presence store (room instance the player is currently in).
|
||||||
// Create with `wrangler kv namespace create MATCH_PRESENCE` and set the id.
|
// Create with `wrangler kv namespace create RECFLARE_MATCH_PRESENCE` and set the id.
|
||||||
"kv_namespaces": [
|
"kv_namespaces": [
|
||||||
{
|
{
|
||||||
"binding": "MATCH_PRESENCE",
|
"binding": "RECFLARE_MATCH_PRESENCE",
|
||||||
"id": "9f53f04b7dd244658d59f515a14748b6"
|
"id": "9f53f04b7dd244658d59f515a14748b6"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// Shared rooms DB (created + migrated by the `rooms` worker; bound read-only here).
|
// Shared `recflare` DB (bound read-only here). The "local" placeholder is replaced
|
||||||
|
// with the real id from RECFLARE_D1 (see .env) at deploy time.
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "rec-rooms",
|
"database_name": "recflare",
|
||||||
"database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5"
|
"database_id": "local"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"logpush": false,
|
"logpush": false,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Player-settings worker served on the `playersettings` subdomain.
|
|||||||
- `PUT /playersettings` — `[Authorize]`. Accepts a form-urlencoded
|
- `PUT /playersettings` — `[Authorize]`. Accepts a form-urlencoded
|
||||||
`key=…&value=…` (or a JSON `{key,value}` / array) and **upserts** it into the
|
`key=…&value=…` (or a JSON `{key,value}` / array) and **upserts** it into the
|
||||||
player's settings, keyed by the `sub` claim of the Bearer JWT. Returns `200`.
|
player's settings, keyed by the `sub` claim of the Bearer JWT. Returns `200`.
|
||||||
Persisted in Workers KV (`PLAYER_SETTINGS`, key `player:<id>`).
|
Persisted in Workers KV (`RECFLARE_PLAYER_SETTINGS`, key `player:<id>`).
|
||||||
|
|
||||||
> A full settings PUT would replace the player's _entire_ settings set on each
|
> A full settings PUT would replace the player's _entire_ settings set on each
|
||||||
> call; we merge instead, so a single-key PUT (e.g. `key=PlayerSessionCount`)
|
> call; we merge instead, so a single-key PUT (e.g. `key=PlayerSessionCount`)
|
||||||
@@ -18,7 +18,7 @@ Player-settings worker served on the `playersettings` subdomain.
|
|||||||
## KV namespace
|
## KV namespace
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wrangler kv namespace create PLAYER_SETTINGS # then put the id in wrangler.jsonc
|
wrangler kv namespace create RECFLARE_PLAYER_SETTINGS # then put the id in wrangler.jsonc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { SharedHonoEnv, SharedHonoVariables } from '@repo/hono-helpers/src/
|
|||||||
|
|
||||||
export type Env = SharedHonoEnv & {
|
export type Env = SharedHonoEnv & {
|
||||||
/** Per-player settings store. Key `player:<id>` → JSON map of `{ key: value }`. */
|
/** Per-player settings store. Key `player:<id>` → JSON map of `{ key: value }`. */
|
||||||
PLAYER_SETTINGS: KVNamespace
|
RECFLARE_PLAYER_SETTINGS: KVNamespace
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Variables can be extended */
|
/** Variables can be extended */
|
||||||
|
|||||||
@@ -89,10 +89,10 @@ const app = new Hono<App>()
|
|||||||
if (id === null) return unauthorized(c)
|
if (id === null) return unauthorized(c)
|
||||||
|
|
||||||
const kvKey = `player:${id}`
|
const kvKey = `player:${id}`
|
||||||
let stored = await c.env.PLAYER_SETTINGS.get<Record<string, string>>(kvKey, 'json')
|
let stored = await c.env.RECFLARE_PLAYER_SETTINGS.get<Record<string, string>>(kvKey, 'json')
|
||||||
if (!stored || Object.keys(stored).length === 0) {
|
if (!stored || Object.keys(stored).length === 0) {
|
||||||
stored = Object.fromEntries(DEFAULT_SETTINGS.map((s) => [s.Key, s.Value]))
|
stored = Object.fromEntries(DEFAULT_SETTINGS.map((s) => [s.Key, s.Value]))
|
||||||
await c.env.PLAYER_SETTINGS.put(kvKey, JSON.stringify(stored))
|
await c.env.RECFLARE_PLAYER_SETTINGS.put(kvKey, JSON.stringify(stored))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.json(Object.entries(stored).map(([Key, Value]) => ({ PlayerId: id, Key, Value })))
|
return c.json(Object.entries(stored).map(([Key, Value]) => ({ PlayerId: id, Key, Value })))
|
||||||
@@ -109,11 +109,11 @@ const app = new Hono<App>()
|
|||||||
if (incoming.length === 0) return c.body(null, 200)
|
if (incoming.length === 0) return c.body(null, 200)
|
||||||
|
|
||||||
const kvKey = `player:${id}`
|
const kvKey = `player:${id}`
|
||||||
const existing = await c.env.PLAYER_SETTINGS.get<Record<string, string>>(kvKey, 'json')
|
const existing = await c.env.RECFLARE_PLAYER_SETTINGS.get<Record<string, string>>(kvKey, 'json')
|
||||||
const merged: Record<string, string> = { ...existing }
|
const merged: Record<string, string> = { ...existing }
|
||||||
for (const { key, value } of incoming) merged[key] = value
|
for (const { key, value } of incoming) merged[key] = value
|
||||||
|
|
||||||
await c.env.PLAYER_SETTINGS.put(kvKey, JSON.stringify(merged))
|
await c.env.RECFLARE_PLAYER_SETTINGS.put(kvKey, JSON.stringify(merged))
|
||||||
return c.body(null, 200)
|
return c.body(null, 200)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ describe('playersettings endpoints', () => {
|
|||||||
expect(settings.find((s) => s.Key === 'PlayerSessionCount')?.Value).toBe('13')
|
expect(settings.find((s) => s.Key === 'PlayerSessionCount')?.Value).toBe('13')
|
||||||
|
|
||||||
// Defaults were persisted to KV.
|
// Defaults were persisted to KV.
|
||||||
const stored = await env.PLAYER_SETTINGS.get<Record<string, string>>('player:100', 'json')
|
const stored = await env.RECFLARE_PLAYER_SETTINGS.get<Record<string, string>>('player:100', 'json')
|
||||||
expect(stored?.['Recroom.OOBE']).toBe('77')
|
expect(stored?.['Recroom.OOBE']).toBe('77')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ describe('playersettings endpoints', () => {
|
|||||||
)
|
)
|
||||||
expect(res.status).toBe(200)
|
expect(res.status).toBe(200)
|
||||||
|
|
||||||
const stored = await env.PLAYER_SETTINGS.get<Record<string, string>>('player:7', 'json')
|
const stored = await env.RECFLARE_PLAYER_SETTINGS.get<Record<string, string>>('player:7', 'json')
|
||||||
expect(stored).toEqual({ PlayerSessionCount: '1' })
|
expect(stored).toEqual({ PlayerSessionCount: '1' })
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ describe('playersettings endpoints', () => {
|
|||||||
putForm({ key: 'B', value: '2' }, await bearer('8'))
|
putForm({ key: 'B', value: '2' }, await bearer('8'))
|
||||||
)
|
)
|
||||||
|
|
||||||
const stored = await env.PLAYER_SETTINGS.get<Record<string, string>>('player:8', 'json')
|
const stored = await env.RECFLARE_PLAYER_SETTINGS.get<Record<string, string>>('player:8', 'json')
|
||||||
expect(stored).toEqual({ A: '1', B: '2' })
|
expect(stored).toEqual({ A: '1', B: '2' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
// Per-player settings persistence.
|
// Per-player settings persistence.
|
||||||
"kv_namespaces": [
|
"kv_namespaces": [
|
||||||
{
|
{
|
||||||
"binding": "PLAYER_SETTINGS",
|
"binding": "RECFLARE_PLAYER_SETTINGS",
|
||||||
"id": "d33a90014e904b0eac720bddcbe0b036"
|
"id": "d33a90014e904b0eac720bddcbe0b036"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,16 +4,17 @@
|
|||||||
"main": "src/rooms.app.ts",
|
"main": "src/rooms.app.ts",
|
||||||
"compatibility_date": "2025-09-20",
|
"compatibility_date": "2025-09-20",
|
||||||
"compatibility_flags": ["nodejs_compat"],
|
"compatibility_flags": ["nodejs_compat"],
|
||||||
// Room storage. Create with `wrangler d1 create rec-rooms`, then put the real
|
// Shared `recflare` DB (room storage lives here). Create it manually with
|
||||||
// id in the gitignored root .env under RECFLARE_D1 (see .env.example) — it is
|
// `wrangler d1 create recflare`, then put the real id in the gitignored root
|
||||||
// spliced in at deploy time by run-wrangler-deploy. The "local" placeholder
|
// .env under RECFLARE_D1 (see .env.example) — it is spliced in at deploy time
|
||||||
// below is only a key for the local SQLite db used by `wrangler dev`, so the
|
// by run-wrangler-deploy. The "local" placeholder below is only a key for the
|
||||||
// committed file needs no per-developer edits. Apply migrations with
|
// local SQLite db used by `wrangler dev`, so the committed file needs no
|
||||||
// `wrangler d1 migrations apply rec-rooms --remote`.
|
// per-developer edits. Apply migrations with
|
||||||
|
// `wrangler d1 migrations apply recflare --remote`.
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
{
|
{
|
||||||
"binding": "DB",
|
"binding": "DB",
|
||||||
"database_name": "rec-rooms",
|
"database_name": "recflare",
|
||||||
"database_id": "local",
|
"database_id": "local",
|
||||||
"migrations_dir": "migrations"
|
"migrations_dir": "migrations"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,18 +37,16 @@ DIR=$(basename "$PWD")
|
|||||||
SUBDOMAIN=$(printf '%s' "$SUBDOMAINS_JSON" | jq -r --arg d "$DIR" '.[$d] // $d')
|
SUBDOMAIN=$(printf '%s' "$SUBDOMAINS_JSON" | jq -r --arg d "$DIR" '.[$d] // $d')
|
||||||
HOST="$SUBDOMAIN.$DOMAIN"
|
HOST="$SUBDOMAIN.$DOMAIN"
|
||||||
|
|
||||||
# Resolve this worker's D1 database id from RECFLARE_D1 (a JSON object keyed by
|
# Splice the shared `recflare` D1 database id from RECFLARE_D1 into a generated
|
||||||
# the worker's directory name) and splice it into a generated config. The
|
# config. All D1-backed workers bind the same database, so RECFLARE_D1 is a single
|
||||||
# committed wrangler.jsonc carries a "local" placeholder so it needs no
|
# id. The committed wrangler.jsonc carries a "local" placeholder so it needs no
|
||||||
# per-developer edits; the real id stays in the gitignored .env / CI secrets.
|
# per-developer edits; the real id stays in the gitignored .env / CI secrets.
|
||||||
# Workers without a D1 binding simply have no placeholder to replace.
|
# Workers without a D1 binding simply have no placeholder to replace.
|
||||||
CONFIG="wrangler.jsonc"
|
CONFIG="wrangler.jsonc"
|
||||||
if grep -q '"database_id": *"local"' wrangler.jsonc 2>/dev/null; then
|
if grep -q '"database_id": *"local"' wrangler.jsonc 2>/dev/null; then
|
||||||
D1_JSON=${RECFLARE_D1:-}
|
DB_ID=${RECFLARE_D1:-}
|
||||||
[ -n "$D1_JSON" ] || D1_JSON='{}'
|
|
||||||
DB_ID=$(printf '%s' "$D1_JSON" | jq -r --arg d "$DIR" '.[$d] // empty')
|
|
||||||
if [ -z "$DB_ID" ]; then
|
if [ -z "$DB_ID" ]; then
|
||||||
echo "error: no D1 id for '$DIR' in RECFLARE_D1 — add it to .env (see .env.example)" >&2
|
echo "error: RECFLARE_D1 is not set — add the recflare D1 id to .env (see .env.example)" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
CONFIG="wrangler.generated.jsonc"
|
CONFIG="wrangler.generated.jsonc"
|
||||||
|
|||||||
Reference in New Issue
Block a user