diff --git a/.env.example b/.env.example index e9a0bf9..e57bbf0 100644 --- a/.env.example +++ b/.env.example @@ -5,7 +5,8 @@ RECFLARE_DOMAIN=rec.example.com # worker's directory name. Defaults to the directory name when unset. # 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 # 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 diff --git a/apps/accounts/src/accounts-db.ts b/apps/accounts/src/accounts-db.ts index ebc0a38..631999d 100644 --- a/apps/accounts/src/accounts-db.ts +++ b/apps/accounts/src/accounts-db.ts @@ -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 * SQLite generated (virtual) columns extracted from that JSON and indexed — * the same JSON-blob pattern the `rooms` worker uses. diff --git a/apps/accounts/wrangler.jsonc b/apps/accounts/wrangler.jsonc index 24ae558..5648e93 100644 --- a/apps/accounts/wrangler.jsonc +++ b/apps/accounts/wrangler.jsonc @@ -4,13 +4,15 @@ "main": "src/accounts.app.ts", "compatibility_date": "2025-09-20", "compatibility_flags": ["nodejs_compat"], - // Shared D1 database. The `accounts` table schema/migrations are owned by the - // `auth` worker; this worker binds it read/write to look up and create accounts. + // Shared `recflare` D1 database. The `accounts` table schema/migrations are owned + // 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": [ { "binding": "DB", - "database_name": "rec-rooms", - "database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5" + "database_name": "recflare", + "database_id": "local" } ], "logpush": false, diff --git a/apps/api/src/api.app.ts b/apps/api/src/api.app.ts index b974dd6..3fd57f0 100644 --- a/apps/api/src/api.app.ts +++ b/apps/api/src/api.app.ts @@ -518,7 +518,7 @@ const app = new Hono({ strict: false }) ) // ---- 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. .get('/roomserver/rooms/bulk', async (c) => { const idParam = c.req.query('id') diff --git a/apps/api/src/rooms-db.ts b/apps/api/src/rooms-db.ts index c5baf97..ce48b78 100644 --- a/apps/api/src/rooms-db.ts +++ b/apps/api/src/rooms-db.ts @@ -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 + * migrations); this worker binds the same database read-only for its * `/roomserver/rooms/*` endpoints. Keep these queries in sync with the rooms diff --git a/apps/api/src/test/integration/api.test.ts b/apps/api/src/test/integration/api.test.ts index f013499..ed0fd9b 100644 --- a/apps/api/src/test/integration/api.test.ts +++ b/apps/api/src/test/integration/api.test.ts @@ -14,7 +14,7 @@ declare module 'cloudflare:test' { 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. const TEST_ROOMS = [ { diff --git a/apps/api/wrangler.jsonc b/apps/api/wrangler.jsonc index 83fbca0..c6b98fb 100644 --- a/apps/api/wrangler.jsonc +++ b/apps/api/wrangler.jsonc @@ -4,12 +4,14 @@ "main": "src/api.app.ts", "compatibility_date": "2025-09-20", "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": [ { "binding": "DB", - "database_name": "rec-rooms", - "database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5" + "database_name": "recflare", + "database_id": "local" } ], // Image bucket shared with the `img` worker (which serves objects back by key). @@ -17,7 +19,7 @@ "r2_buckets": [ { "binding": "IMAGES", - "bucket_name": "rec-img" + "bucket_name": "recflare-img" } ], "logpush": false, diff --git a/apps/auth/src/accounts-db.ts b/apps/auth/src/accounts-db.ts index b2c961c..b92d3d2 100644 --- a/apps/auth/src/accounts-db.ts +++ b/apps/auth/src/accounts-db.ts @@ -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 * SQLite generated (virtual) columns extracted from that JSON and indexed — * the same JSON-blob pattern the `rooms` worker uses. diff --git a/apps/auth/src/auth.app.ts b/apps/auth/src/auth.app.ts index cc8032d..41f6ed0 100644 --- a/apps/auth/src/auth.app.ts +++ b/apps/auth/src/auth.app.ts @@ -87,7 +87,7 @@ async function placeNewPlayerInOrientation(env: App['Bindings'], accountId: numb platform: 0, 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, }) } diff --git a/apps/auth/src/context.ts b/apps/auth/src/context.ts index 6a53a54..6810518 100644 --- a/apps/auth/src/context.ts +++ b/apps/auth/src/context.ts @@ -8,7 +8,7 @@ export type Env = SharedHonoEnv & { // 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 // heartbeat keeps them there instead of bouncing them to the dorm. - MATCH_PRESENCE: KVNamespace + RECFLARE_MATCH_PRESENCE: KVNamespace } /** Variables can be extended */ diff --git a/apps/auth/src/test/integration/api.test.ts b/apps/auth/src/test/integration/api.test.ts index 3ba7c4a..17775e0 100644 --- a/apps/auth/src/test/integration/api.test.ts +++ b/apps/auth/src/test/integration/api.test.ts @@ -139,7 +139,7 @@ describe('auth worker routes', () => { 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 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 } }>(`presence:${sub}`, 'json') expect(presence).not.toBeNull() diff --git a/apps/auth/wrangler.jsonc b/apps/auth/wrangler.jsonc index 394d28e..8c320f0 100644 --- a/apps/auth/wrangler.jsonc +++ b/apps/auth/wrangler.jsonc @@ -4,14 +4,16 @@ "main": "src/auth.app.ts", "compatibility_date": "2025-09-20", "compatibility_flags": ["nodejs_compat"], - // Shared D1 database (also used by the rooms worker). The `auth` worker owns - // the `accounts` table; a dedicated migrations_table keeps its migration - // history separate from the rooms worker's migrations on the same database. + // Shared `recflare` D1 database (also used by the rooms worker). The `auth` worker + // owns the `accounts` table; a dedicated migrations_table keeps its migration + // 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": [ { "binding": "DB", - "database_name": "rec-rooms", - "database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5", + "database_name": "recflare", + "database_id": "local", "migrations_dir": "migrations", "migrations_table": "d1_migrations_auth" } @@ -20,7 +22,7 @@ // accounts into the Orientation room on signup. "kv_namespaces": [ { - "binding": "MATCH_PRESENCE", + "binding": "RECFLARE_MATCH_PRESENCE", "id": "9f53f04b7dd244658d59f515a14748b6" } ], diff --git a/apps/cdn/wrangler.jsonc b/apps/cdn/wrangler.jsonc index 8ef2a74..f749365 100644 --- a/apps/cdn/wrangler.jsonc +++ b/apps/cdn/wrangler.jsonc @@ -11,7 +11,7 @@ "r2_buckets": [ { "binding": "CDN_ASSETS", - "bucket_name": "rec-cdn" + "bucket_name": "recflare-cdn" } ], "upload_source_maps": true, diff --git a/apps/img/README.md b/apps/img/README.md index ce9bc61..b12f1c8 100644 --- a/apps/img/README.md +++ b/apps/img/README.md @@ -2,7 +2,7 @@ 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: - `GET /` — service status `{ "service": "img", "status": "ok" }`. @@ -37,7 +37,7 @@ node -e "const{generateKeyPairSync}=require('crypto');const{publicKey,privateKey ## One-time bucket setup ```sh -wrangler r2 bucket create rec-img +wrangler r2 bucket create recflare-img ``` ## 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: ```sh -wrangler r2 object put rec-img/DefaultProfileImage.jpg \ +wrangler r2 object put recflare-img/DefaultProfileImage.jpg \ --file=apps/img/static/DefaultProfileImage.jpg \ --content-type=image/jpeg --remote ``` diff --git a/apps/img/wrangler.jsonc b/apps/img/wrangler.jsonc index d2a12ee..33c6d18 100644 --- a/apps/img/wrangler.jsonc +++ b/apps/img/wrangler.jsonc @@ -8,7 +8,7 @@ "r2_buckets": [ { "binding": "IMAGES", - "bucket_name": "rec-img" + "bucket_name": "recflare-img" } ], "upload_source_maps": true, diff --git a/apps/match/src/context.ts b/apps/match/src/context.ts index a7f6634..caa40a3 100644 --- a/apps/match/src/context.ts +++ b/apps/match/src/context.ts @@ -5,7 +5,7 @@ export type Env = SharedHonoEnv & { // Per-player presence (the room instance they're currently in). Written by // matchmake/goto, read by the heartbeat, cleared on login — mirrors the // 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 // room's real scene/subroom when matchmaking into it. DB: D1Database diff --git a/apps/match/src/match.app.ts b/apps/match/src/match.app.ts index 8f9a0f7..b1b8d2b 100644 --- a/apps/match/src/match.app.ts +++ b/apps/match/src/match.app.ts @@ -98,14 +98,14 @@ const presenceKey = (id: number) => `presence:${id}` /** Persist the player's presence (room instance + status), refreshing the TTL. */ async function setPresence(c: Context, id: number, presence: Presence): Promise { - 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, }) } /** Read the player's stored presence, or null when they aren't in a room. */ async function getPresence(c: Context, id: number): Promise { - return c.env.MATCH_PRESENCE.get(presenceKey(id), 'json') + return c.env.RECFLARE_MATCH_PRESENCE.get(presenceKey(id), 'json') } /** Store the room instance the player just matchmade into, preserving status. */ diff --git a/apps/match/src/rooms-db.ts b/apps/match/src/rooms-db.ts index 8496f19..25eea05 100644 --- a/apps/match/src/rooms-db.ts +++ b/apps/match/src/rooms-db.ts @@ -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 + * 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 diff --git a/apps/match/src/test/integration/api.test.ts b/apps/match/src/test/integration/api.test.ts index 11b010d..56a2fab 100644 --- a/apps/match/src/test/integration/api.test.ts +++ b/apps/match/src/test/integration/api.test.ts @@ -12,7 +12,7 @@ declare module 'cloudflare:test' { 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). const RECCENTER_SCENE = 'cbad71af-0831-44d8-b8ef-69edafa841f6' const TEST_ROOMS = [ diff --git a/apps/match/wrangler.jsonc b/apps/match/wrangler.jsonc index d88901c..f9120ed 100644 --- a/apps/match/wrangler.jsonc +++ b/apps/match/wrangler.jsonc @@ -5,19 +5,20 @@ "compatibility_date": "2025-09-20", "compatibility_flags": ["nodejs_compat"], // 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": [ { - "binding": "MATCH_PRESENCE", + "binding": "RECFLARE_MATCH_PRESENCE", "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": [ { "binding": "DB", - "database_name": "rec-rooms", - "database_id": "d44083e1-5bfe-4467-aa9a-f13c5c2496d5" + "database_name": "recflare", + "database_id": "local" } ], "logpush": false, diff --git a/apps/playersettings/README.md b/apps/playersettings/README.md index e363ac4..62830f5 100644 --- a/apps/playersettings/README.md +++ b/apps/playersettings/README.md @@ -9,7 +9,7 @@ Player-settings worker served on the `playersettings` subdomain. - `PUT /playersettings` — `[Authorize]`. Accepts a form-urlencoded `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`. - Persisted in Workers KV (`PLAYER_SETTINGS`, key `player:`). + Persisted in Workers KV (`RECFLARE_PLAYER_SETTINGS`, key `player:`). > 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`) @@ -18,7 +18,7 @@ Player-settings worker served on the `playersettings` subdomain. ## KV namespace ```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 diff --git a/apps/playersettings/src/context.ts b/apps/playersettings/src/context.ts index 7888418..251448b 100644 --- a/apps/playersettings/src/context.ts +++ b/apps/playersettings/src/context.ts @@ -3,7 +3,7 @@ import type { SharedHonoEnv, SharedHonoVariables } from '@repo/hono-helpers/src/ export type Env = SharedHonoEnv & { /** Per-player settings store. Key `player:` → JSON map of `{ key: value }`. */ - PLAYER_SETTINGS: KVNamespace + RECFLARE_PLAYER_SETTINGS: KVNamespace } /** Variables can be extended */ diff --git a/apps/playersettings/src/playersettings.app.ts b/apps/playersettings/src/playersettings.app.ts index 676c22a..5d1c26c 100644 --- a/apps/playersettings/src/playersettings.app.ts +++ b/apps/playersettings/src/playersettings.app.ts @@ -89,10 +89,10 @@ const app = new Hono() if (id === null) return unauthorized(c) const kvKey = `player:${id}` - let stored = await c.env.PLAYER_SETTINGS.get>(kvKey, 'json') + let stored = await c.env.RECFLARE_PLAYER_SETTINGS.get>(kvKey, 'json') if (!stored || Object.keys(stored).length === 0) { 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 }))) @@ -109,11 +109,11 @@ const app = new Hono() if (incoming.length === 0) return c.body(null, 200) const kvKey = `player:${id}` - const existing = await c.env.PLAYER_SETTINGS.get>(kvKey, 'json') + const existing = await c.env.RECFLARE_PLAYER_SETTINGS.get>(kvKey, 'json') const merged: Record = { ...existing } 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) }) diff --git a/apps/playersettings/src/test/integration/api.test.ts b/apps/playersettings/src/test/integration/api.test.ts index 880a641..cf9d5d3 100644 --- a/apps/playersettings/src/test/integration/api.test.ts +++ b/apps/playersettings/src/test/integration/api.test.ts @@ -70,7 +70,7 @@ describe('playersettings endpoints', () => { expect(settings.find((s) => s.Key === 'PlayerSessionCount')?.Value).toBe('13') // Defaults were persisted to KV. - const stored = await env.PLAYER_SETTINGS.get>('player:100', 'json') + const stored = await env.RECFLARE_PLAYER_SETTINGS.get>('player:100', 'json') expect(stored?.['Recroom.OOBE']).toBe('77') }) @@ -97,7 +97,7 @@ describe('playersettings endpoints', () => { ) expect(res.status).toBe(200) - const stored = await env.PLAYER_SETTINGS.get>('player:7', 'json') + const stored = await env.RECFLARE_PLAYER_SETTINGS.get>('player:7', 'json') expect(stored).toEqual({ PlayerSessionCount: '1' }) }) @@ -111,7 +111,7 @@ describe('playersettings endpoints', () => { putForm({ key: 'B', value: '2' }, await bearer('8')) ) - const stored = await env.PLAYER_SETTINGS.get>('player:8', 'json') + const stored = await env.RECFLARE_PLAYER_SETTINGS.get>('player:8', 'json') expect(stored).toEqual({ A: '1', B: '2' }) }) diff --git a/apps/playersettings/wrangler.jsonc b/apps/playersettings/wrangler.jsonc index 29b5f06..204cb4e 100644 --- a/apps/playersettings/wrangler.jsonc +++ b/apps/playersettings/wrangler.jsonc @@ -7,7 +7,7 @@ // Per-player settings persistence. "kv_namespaces": [ { - "binding": "PLAYER_SETTINGS", + "binding": "RECFLARE_PLAYER_SETTINGS", "id": "d33a90014e904b0eac720bddcbe0b036" } ], diff --git a/apps/rooms/wrangler.jsonc b/apps/rooms/wrangler.jsonc index 45963ac..9a2c95c 100644 --- a/apps/rooms/wrangler.jsonc +++ b/apps/rooms/wrangler.jsonc @@ -4,16 +4,17 @@ "main": "src/rooms.app.ts", "compatibility_date": "2025-09-20", "compatibility_flags": ["nodejs_compat"], - // Room storage. Create with `wrangler d1 create rec-rooms`, then put the real - // id in the gitignored root .env under RECFLARE_D1 (see .env.example) — it is - // spliced in at deploy time by run-wrangler-deploy. The "local" placeholder - // below is only a key for the local SQLite db used by `wrangler dev`, so the - // committed file needs no per-developer edits. Apply migrations with - // `wrangler d1 migrations apply rec-rooms --remote`. + // Shared `recflare` DB (room storage lives here). Create it manually with + // `wrangler d1 create recflare`, then put the real id in the gitignored root + // .env under RECFLARE_D1 (see .env.example) — it is spliced in at deploy time + // by run-wrangler-deploy. The "local" placeholder below is only a key for the + // local SQLite db used by `wrangler dev`, so the committed file needs no + // per-developer edits. Apply migrations with + // `wrangler d1 migrations apply recflare --remote`. "d1_databases": [ { "binding": "DB", - "database_name": "rec-rooms", + "database_name": "recflare", "database_id": "local", "migrations_dir": "migrations" } diff --git a/packages/tools/bin/run-wrangler-deploy b/packages/tools/bin/run-wrangler-deploy index 666acce..c4479da 100755 --- a/packages/tools/bin/run-wrangler-deploy +++ b/packages/tools/bin/run-wrangler-deploy @@ -37,18 +37,16 @@ DIR=$(basename "$PWD") SUBDOMAIN=$(printf '%s' "$SUBDOMAINS_JSON" | jq -r --arg d "$DIR" '.[$d] // $d') HOST="$SUBDOMAIN.$DOMAIN" -# Resolve this worker's D1 database id from RECFLARE_D1 (a JSON object keyed by -# the worker's directory name) and splice it into a generated config. The -# committed wrangler.jsonc carries a "local" placeholder so it needs no +# Splice the shared `recflare` D1 database id from RECFLARE_D1 into a generated +# config. All D1-backed workers bind the same database, so RECFLARE_D1 is a single +# 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. # Workers without a D1 binding simply have no placeholder to replace. CONFIG="wrangler.jsonc" if grep -q '"database_id": *"local"' wrangler.jsonc 2>/dev/null; then - D1_JSON=${RECFLARE_D1:-} - [ -n "$D1_JSON" ] || D1_JSON='{}' - DB_ID=$(printf '%s' "$D1_JSON" | jq -r --arg d "$DIR" '.[$d] // empty') + DB_ID=${RECFLARE_D1:-} 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 fi CONFIG="wrangler.generated.jsonc"