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.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
@@ -10,6 +11,11 @@ pub struct Config {
|
||||
/// 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 {
|
||||
@@ -33,6 +39,16 @@ impl Config {
|
||||
.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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user