mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 14:41:28 -07:00
add game config configuration
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Read an integer worker var, falling back to `fallback` when it is unset or unusable.
|
||||
*
|
||||
* A var arrives as a number when it's declared in wrangler.jsonc `vars`, but as a string
|
||||
* when it's set anywhere else (the dashboard, `wrangler deploy --var`, `.dev.vars`), so
|
||||
* both have to be accepted — the same var is a different type depending on where the
|
||||
* operator set it.
|
||||
*
|
||||
* Anything that isn't a finite integer (an empty string, a typo, `3.5`) is treated as
|
||||
* unset rather than coerced: `Number.parseInt` would read `"3abc"` as 3 and `"3.9"` as 3,
|
||||
* which turns a typo into a silently wrong limit. Falling back to the documented default
|
||||
* is the safe failure here.
|
||||
*/
|
||||
export function intVar(value: unknown, fallback: number): number {
|
||||
if (typeof value === 'number') return Number.isInteger(value) ? value : fallback
|
||||
if (typeof value !== 'string' || value.trim() === '') return fallback
|
||||
const parsed = Number(value)
|
||||
return Number.isInteger(parsed) ? parsed : fallback
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export type { HonoApp, SharedHonoEnv, SharedHonoVariables, SharedAppContext } from './types'
|
||||
export * from './helpers/env'
|
||||
export { logger } from './helpers/logger'
|
||||
export { getRequestLogData, type LogDataRequest } from './helpers/request'
|
||||
export * from './helpers/errors'
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
. "$(git rev-parse --show-toplevel)/packages/tools/src/sh/env.sh"
|
||||
|
||||
# Extract name and version from package.json using jq
|
||||
NAME=$(jq -r '.name' package.json)
|
||||
VERSION=$(get-version)
|
||||
|
||||
# Everything an operator supplies — domain, resource ids, tuning knobs — comes from the
|
||||
# single gitignored .env at the repo root (in CI, from exported secrets, which win over the
|
||||
# file). See .env.example.
|
||||
recflare_load_env
|
||||
|
||||
# Resolve the base domain (and this worker's subdomain), then deploy onto the
|
||||
# custom domain via `--domain`. This keeps the real domain out of versioned files
|
||||
# — committed wrangler.jsonc has no routes, and the base domain is passed as the
|
||||
# DOMAIN var at runtime.
|
||||
#
|
||||
# The domain comes from the RECFLARE_DOMAIN env var. For local dev that's set in a
|
||||
# gitignored .env at the repo root; in CI it's an exported secret. An already-set
|
||||
# RECFLARE_DOMAIN wins and skips the file. Per-app subdomain overrides come from
|
||||
# RECFLARE_SUBDOMAINS (a JSON object, e.g. {"playersettings":"settings"}).
|
||||
if [ -z "${RECFLARE_DOMAIN:-}" ]; then
|
||||
ENV_FILE="$(git rev-parse --show-toplevel)/.env"
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
set -a
|
||||
. "$ENV_FILE"
|
||||
set +a
|
||||
fi
|
||||
fi
|
||||
|
||||
# DOMAIN var at runtime. Per-app subdomain overrides come from RECFLARE_SUBDOMAINS
|
||||
# (a JSON object, e.g. {"playersettings":"settings"}).
|
||||
if [ -z "${RECFLARE_DOMAIN:-}" ]; then
|
||||
echo "error: RECFLARE_DOMAIN is not set — export it or add it to .env (see .env.example)" >&2
|
||||
exit 1
|
||||
@@ -129,6 +123,12 @@ if [ "$CONFIG" = "wrangler.jsonc" ] && { [ -n "$NEEDS_D1" ] || [ -n "$NEEDS_KV"
|
||||
fi
|
||||
fi
|
||||
|
||||
# The operator's tuning knobs, injected the same way as the resource ids above: each lives
|
||||
# in the .env as RECFLARE_<VAR> and rides along as a `--var`. See recflare_vars in
|
||||
# packages/tools/src/sh/env.sh. run-wrangler-dev passes the same flags, so one .env tunes
|
||||
# both a deploy and a local dev server.
|
||||
EXTRA_VARS=$(recflare_vars)
|
||||
|
||||
# Vite-built configs set no_bundle (vite already bundled and minified), which is
|
||||
# incompatible with --minify. Only pass --minify when wrangler does the bundling.
|
||||
MINIFY="--minify"
|
||||
@@ -136,11 +136,14 @@ MINIFY="--minify"
|
||||
|
||||
# Deploy with wrangler using the extracted values as binding variables
|
||||
echo "Deploying worker $NAME version $VERSION to $HOST"
|
||||
# $EXTRA_VARS is intentionally unquoted — it's a flag list to word-split, and every
|
||||
# value in it is an integer, so there's nothing to split on inside a value.
|
||||
wrangler deploy \
|
||||
--config "$CONFIG" \
|
||||
--var NAME:"$NAME" \
|
||||
--var SENTRY_RELEASE:"$VERSION" \
|
||||
--var DOMAIN:"$DOMAIN" \
|
||||
$EXTRA_VARS \
|
||||
--domain "$HOST" \
|
||||
$MINIFY \
|
||||
"$@"
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
. "$(git rev-parse --show-toplevel)/packages/tools/src/sh/env.sh"
|
||||
|
||||
NAME=$(jq -r '.name' package.json)
|
||||
|
||||
# Tuning knobs come from the same gitignored root .env a deploy reads (RECFLARE_<VAR>, see
|
||||
# .env.example), so a knob is configured in exactly one place whether you're running locally
|
||||
# or shipping. Unset knobs fall back to the worker's own default constants, same as a deploy.
|
||||
#
|
||||
# Passed as `--var` rather than left to wrangler's own .env loading: wrangler only reads a
|
||||
# .env sitting next to the worker's wrangler.jsonc, which would mean a second file per app.
|
||||
recflare_load_env
|
||||
EXTRA_VARS=$(recflare_vars)
|
||||
|
||||
# Give each worker a stable, unique dev port so `turbo dev` can run them all in
|
||||
# parallel without colliding on wrangler's default 8787 (and its 9229 inspector
|
||||
# port). The offset is the worker's alphabetical position among its siblings, so
|
||||
@@ -16,8 +27,10 @@ OFFSET=$(
|
||||
PORT=$((8787 + OFFSET - 1))
|
||||
INSPECTOR_PORT=$((9229 + OFFSET - 1))
|
||||
|
||||
# $EXTRA_VARS is intentionally unquoted — it's a flag list to word-split on.
|
||||
exec wrangler dev \
|
||||
--var NAME:"$NAME" \
|
||||
$EXTRA_VARS \
|
||||
--port "$PORT" \
|
||||
--inspector-port "$INSPECTOR_PORT" \
|
||||
"$@"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
. "$(git rev-parse --show-toplevel)/packages/tools/src/sh/env.sh"
|
||||
|
||||
# Apply this worker's D1 migrations. Run from a worker directory (e.g. via
|
||||
# `bun turbo -F rooms migrate`). Defaults to --remote; pass --local to target the
|
||||
# dev SQLite db. Extra args pass through to `wrangler d1 migrations apply`.
|
||||
@@ -41,16 +43,8 @@ if [ "$LOCAL" -eq 1 ]; then
|
||||
exec wrangler d1 migrations apply "$DB_NAME" "$@"
|
||||
fi
|
||||
|
||||
# Load RECFLARE_D1 from the gitignored root .env if not already set (mirrors
|
||||
# run-wrangler-deploy's handling of RECFLARE_DOMAIN). An already-set value wins.
|
||||
if [ -z "${RECFLARE_D1:-}" ]; then
|
||||
ENV_FILE="$(git rev-parse --show-toplevel)/.env"
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
set -a
|
||||
. "$ENV_FILE"
|
||||
set +a
|
||||
fi
|
||||
fi
|
||||
# RECFLARE_D1 comes from the gitignored root .env, or from CI secrets, which win over it.
|
||||
recflare_load_env
|
||||
|
||||
DB_ID=${RECFLARE_D1:-}
|
||||
if [ -z "$DB_ID" ]; then
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/bin/sh
|
||||
# Shared by the run-wrangler-* scripts. Source it, don't run it:
|
||||
#
|
||||
# . "$(git rev-parse --show-toplevel)/packages/tools/src/sh/env.sh"
|
||||
#
|
||||
# It lives outside bin/ on purpose — package.json sets directories.bin to bin/, so anything
|
||||
# in there becomes a runnable command in node_modules/.bin.
|
||||
#
|
||||
# RecFlare keeps a single gitignored .env at the repo root (see .env.example) holding
|
||||
# everything an operator has to supply: their domain, the ids of the storage resources they
|
||||
# created, and any tuning knobs they want to change. That one file feeds both `just deploy`
|
||||
# and `just dev`, so a value is never configured twice.
|
||||
|
||||
# Names the deploy scripts consume themselves — the domain and the ids of the operator's
|
||||
# Cloudflare resources. Everything else in .env is worker config; see recflare_vars.
|
||||
RECFLARE_RESERVED="DOMAIN SUBDOMAINS D1 KV SECRETS_STORE ENV_LOADED"
|
||||
|
||||
# Load the root .env, letting anything already in the environment win. The file is a local
|
||||
# convenience; CI exports the same names as secrets and must not be clobbered by a stray
|
||||
# .env in a checkout. Safe to call more than once.
|
||||
recflare_load_env() {
|
||||
[ -z "${RECFLARE_ENV_LOADED:-}" ] || return 0
|
||||
RECFLARE_ENV_LOADED=1
|
||||
|
||||
_env_file="$(git rev-parse --show-toplevel)/.env"
|
||||
[ -f "$_env_file" ] || return 0
|
||||
|
||||
# `export -p` re-emits the already-exported values as quoted assignments, so we can put
|
||||
# them back after the file has had its say.
|
||||
_preset=$(export -p | grep -E '(^|[[:space:]])RECFLARE_[A-Za-z0-9_]+=' || true)
|
||||
set -a
|
||||
. "$_env_file"
|
||||
set +a
|
||||
eval "$_preset"
|
||||
|
||||
unset _env_file _preset
|
||||
}
|
||||
|
||||
# Echo the `--var` flags carrying the operator's tuning knobs, e.g.
|
||||
# " --var MAX_ACCOUNTS_PER_IP:10 --var STARTING_TOKENS:250".
|
||||
#
|
||||
# This is a convention, not a list kept here: every RECFLARE_<VAR> in the environment that
|
||||
# isn't one of the RECFLARE_RESERVED deploy inputs above is handed to the worker as
|
||||
# `--var <VAR>:<value>`. So RECFLARE_MAX_ACCOUNTS_PER_IP=10 gives every worker
|
||||
# MAX_ACCOUNTS_PER_IP=10 — the workers that don't read it simply ignore it, and two workers
|
||||
# that read the same knob agree on it for free. Adding a knob means declaring it in the
|
||||
# worker's context.ts, reading it there, and documenting it in .env.example; these scripts
|
||||
# never need to change and stay free of any knowledge of specific app names.
|
||||
#
|
||||
# Every knob is optional: unset means no `--var` at all, so the worker falls back to the
|
||||
# default constant in its own source, and deleting a line from .env really does restore that
|
||||
# default on the next deploy. (Vars are replaced wholesale by a deploy — which is exactly
|
||||
# why a value set in the Cloudflare dashboard doesn't survive one.)
|
||||
#
|
||||
# Values must not contain whitespace: the result is a flag list the caller word-splits.
|
||||
# Knobs are numbers and short enums, and real secrets belong in the Secrets Store (which is
|
||||
# bound in wrangler.jsonc, not passed through here), so this hasn't been worth the ceremony
|
||||
# of an array. Vars also arrive in the Worker as strings (`--var X:3` is "3", not 3), which
|
||||
# is why the workers parse them through `intVar` rather than reading them as numbers.
|
||||
recflare_vars() {
|
||||
# The sed only ever yields [A-Z0-9_] names, so the eval below can't expand anything else.
|
||||
for _name in $(env | sed -n 's/^RECFLARE_\([A-Z0-9_][A-Z0-9_]*\)=.*/\1/p'); do
|
||||
case " $RECFLARE_RESERVED " in
|
||||
*" $_name "*) continue ;;
|
||||
esac
|
||||
|
||||
eval "_value=\${RECFLARE_${_name}}"
|
||||
[ -n "$_value" ] || continue
|
||||
printf ' --var %s:%s' "$_name" "$_value"
|
||||
done
|
||||
|
||||
unset _name _value
|
||||
}
|
||||
Reference in New Issue
Block a user