Files
recflare/apps/ns/src/endpoints.ts
T
devin 178d3b5b0e support for 202507 endpoints (#37)
* [auth][api] accept the 20250424.01 client

* [2025] unstable

* 20250718.0

* correct one this time

* stubs

* more stubs

* more stubs

* [lists] add worker

* [ai] route stubs

* [api] player photo setting

* [econ] add roomEconConfig route

* [infra] update worker generators

* [worker] add cards/moderation/platformnotification workers

* [lists] updates to some endpoints

* [clubs] stub out announcement endpoint, for now

* [econ] stub out season endpoints for now

* [chat] apps/chat stub out party endpoint not sure the shape yet

* [api] stub out statsig and lockeditems

* [doc] new services

* [lists] stub the bulk endpoint

* [datacollection] add placeholder service until we can kill it

* [api] set gifting to lvl5

* update lock

* [cdn] enable cache

* [match] matchmake v2

* [lists] stub some lists

* [ai] stubs

* [rooms] new subroom save endpoint

* [econ] add bulk purchase endpoint

* [discovery] update featured creator to 1 for fun

* [api] add photo settings flag

* [chat] fixup chat permissions (sorta)

* [auth] restrictions endpoint

* [rooms] contributed endpoint

* [api] fix outfit endpoint

* [discovery] attempt to fix store

* [chat] privacy endpoints

* [api] cheered images

* [rooms] add xp endpoint (disbaled)

* [rooms] add xp endpoint (disabled)

* update images-db for cheers

* [rooms] add autocomplete endpoint

* [cdn/img] increase cache ttl for statics

* [api] bulk route for images

* [accounts] add banner image

* [api] add misc missing endpoints

* [discovery] remove AI tab

* [platformnotifications] stub some endpoints

* [lists] add some more lists

* [rooms] additional endpoints

* [chat] stub a few privacy endpoints

* [econ] stub some endpoints

* misc db fixes

* [api] tweak shape for images v6

* [rooms] dont show trending RROs
2026-08-21 15:15:55 -04:00

94 lines
3.1 KiB
TypeScript

/**
* Service-discovery map: service label → default subdomain. The game client fetches the
* generated `{ label: "https://<subdomain>.<domain>" }` document from `/`.
*
* The base domain is injected at deploy time via the `DOMAIN` var (see
* `run-wrangler-deploy`), so the real domain never lives in a versioned file. The
* subdomains here are defaults — an operator redirects any of them from `.env`, see
* `applyOverrides` below.
*/
const SERVICE_SUBDOMAINS = {
Accounts: 'accounts',
AI: 'ai',
API: 'api',
Auth: 'auth',
BugReporting: 'bugreporting',
Cards: 'cards',
CDN: 'cdn',
Chat: 'chat',
Clubs: 'clubs',
CMS: 'cms',
Commerce: 'commerce',
Data: 'data',
DataCollection: 'datacollection',
Discovery: 'discovery',
Econ: 'econ',
GameLogs: 'gamelogs',
Geo: 'geo',
Images: 'img',
Leaderboard: 'leaderboard',
Link: 'link',
Lists: 'lists',
Matchmaking: 'match',
Moderation: 'moderation',
Notifications: 'notify',
PlatformNotifications: 'platformnotifications',
PlayerSettings: 'playersettings',
RoomComments: 'roomcomments',
RoomieIntegrations: 'roomieintegrations',
Rooms: 'rooms',
Storage: 'storage',
Strings: 'strings',
StringsCDN: 'strings-cdn',
Studio: 'studio',
Thorn: 'thorn',
Videos: 'videos',
WWW: 'www',
} as const
/**
* Parses the `SUBDOMAINS` var — the operator's `RECFLARE_SUBDOMAINS` object, injected at
* deploy time by `run-wrangler-deploy`.
*
* It is keyed by the DEFAULT subdomain above, not by the service label, because the deploy
* script reads the very same object keyed by a worker's directory name — and every worker's
* directory name is its default subdomain. So one `.env` entry moves both sides at once:
* `{"playersettings":"settings"}` both deploys the `playersettings` worker onto
* `settings.<domain>` and advertises that host to the client. Entries naming a service with
* no worker of its own are pure client-side redirects — `{"moderation":"api"}` points the
* client's Moderation calls at the `api` worker, which is where the
* `/api/PlayerReporting/…` routes actually live.
*
* A malformed value is ignored rather than thrown: this document is the first thing the
* client fetches, so a typo in `.env` should cost one redirect, not every service host.
*/
function parseOverrides(subdomains: string | undefined): Record<string, string> {
if (!subdomains) return {}
let parsed: unknown
try {
parsed = JSON.parse(subdomains)
} catch {
return {}
}
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return {}
return Object.fromEntries(
Object.entries(parsed).filter(
(entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1] !== ''
)
)
}
/**
* Builds the endpoints document for `domain`, e.g. `rec.example.com`, applying any
* subdomain overrides from `subdomains` (the raw `SUBDOMAINS` var JSON).
*/
export function buildEndpoints(domain: string, subdomains?: string): Record<string, string> {
const overrides = parseOverrides(subdomains)
return Object.fromEntries(
Object.entries(SERVICE_SUBDOMAINS).map(([label, sub]) => [
label,
`https://${overrides[sub] ?? sub}.${domain}`,
])
)
}