"""Configuration management — persists Mealie and Tandoor connection settings to a JSON file.""" import json import os from pathlib import Path DATA_DIR = Path(os.environ.get("DATA_DIR", "/data")) CONFIG_FILE = DATA_DIR / "config.json" # Optional internal URLs for Docker-to-Docker API calls (avoids Cloudflare hairpin). # The user-facing URLs are still used for browser links. MEALIE_INTERNAL_URL = os.environ.get("MEALIE_INTERNAL_URL", "").strip().rstrip("/") TANDOOR_INTERNAL_URL = os.environ.get("TANDOOR_INTERNAL_URL", "").strip().rstrip("/") _DEFAULTS = { "mealie_url": "", "mealie_api_key": "", "tandoor_url": "", "tandoor_api_key": "", } # Environment variable overrides for connection settings. # When set, these take priority over values stored in config.json. _ENV_OVERRIDES = { "mealie_url": os.environ.get("MEALIE_URL", "").strip().rstrip("/"), "mealie_api_key": os.environ.get("MEALIE_API_KEY", "").strip(), "tandoor_url": os.environ.get("TANDOOR_URL", "").strip().rstrip("/"), "tandoor_api_key": os.environ.get("TANDOOR_API_KEY", "").strip(), } def _ensure_dir(): DATA_DIR.mkdir(parents=True, exist_ok=True) def load() -> dict: """Return the current config dict, merged with defaults. Environment variables (MEALIE_URL, MEALIE_API_KEY, TANDOOR_URL, TANDOOR_API_KEY) take priority over file-based values when set. """ cfg = dict(_DEFAULTS) if CONFIG_FILE.exists(): try: with open(CONFIG_FILE, "r", encoding="utf-8") as f: cfg.update(json.load(f)) except (json.JSONDecodeError, OSError): pass # Apply env overrides (only non-empty values). for key, val in _ENV_OVERRIDES.items(): if val: cfg[key] = val return cfg def save(cfg: dict): """Atomically persist *cfg* to disk.""" _ensure_dir() tmp = CONFIG_FILE.with_suffix(".tmp") with open(tmp, "w", encoding="utf-8") as f: json.dump(cfg, f, indent=2, ensure_ascii=False) tmp.replace(CONFIG_FILE)