Files
OpenFUT-Core/src/config.rs
T
funman300 352ad11bc4 feat(content): production content-pack loader + referenced-definition preflight
Production real-profile content is loaded via an explicit path, NOT the dev-only
OPENFUT_DEV_CONTENT_GAMES gate:
- Config.content_packs from env OPENFUT_CONTENT_PACKS (comma-sep file paths).
- CardDb::load_pack(path): merge an explicit CardDefinition[] production pack.
- app::build loads dev packs then production packs.

Preflight (app::build, always on): every owned_cards.card_id MUST resolve to a
loaded CardDefinition. A real profile with owned players but even ONE missing
definition fails LOUDLY instead of silently serving an empty /collection; an
empty owned_cards table (fresh DB / tests) passes.

2 preflight integration tests (missing def fails, loaded def passes). clippy
-D warnings clean; full suite 151 tests green.
2026-08-12 19:49:14 +00:00

55 lines
2.1 KiB
Rust

use anyhow::Result;
use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct Config {
pub listen_addr: String,
pub database_url: String,
pub data_dir: String,
pub max_connections: u32,
/// Games whose opt-in development content pack (`data/games/<game>/dev/`) is
/// loaded IN ADDITION to the default `data/cards` catalog. Empty by default —
/// default/test content is never affected unless a game is named here.
pub dev_content_games: Vec<String>,
/// Explicit PRODUCTION content pack file paths (each a `CardDefinition[]`
/// JSON), loaded IN ADDITION to `data/cards` and any dev pack. This is the
/// production real-profile content path — deliberately NOT gated behind the
/// dev-only `dev_content_games`.
pub content_packs: Vec<PathBuf>,
}
impl Config {
pub fn from_env() -> Result<Self> {
Ok(Self {
listen_addr: std::env::var("LISTEN_ADDR").unwrap_or_else(|_| "127.0.0.1:8080".into()),
database_url: std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "sqlite://openfut.db".into()),
data_dir: std::env::var("DATA_DIR").unwrap_or_else(|_| "data".into()),
max_connections: std::env::var("DB_MAX_CONNECTIONS")
.ok()
.and_then(|v| v.parse().ok())
.unwrap_or(5),
dev_content_games: std::env::var("OPENFUT_DEV_CONTENT_GAMES")
.ok()
.map(|v| {
v.split(',')
.map(str::trim)
.filter(|s| !s.is_empty())
.map(String::from)
.collect()
})
.unwrap_or_default(),
content_packs: std::env::var("OPENFUT_CONTENT_PACKS")
.ok()
.map(|v| {
v.split(',')
.map(str::trim)
.filter(|s| !s.is_empty())
.map(PathBuf::from)
.collect()
})
.unwrap_or_default(),
})
}
}