"""Persistência e consulta de módulos activos.""" from __future__ import annotations import json import os from pathlib import Path from app.modules.registry import MODULE_BY_ID, MODULES MODULES_PATH = Path(os.getenv("DESK_MODULES_PATH", "/data/desk_modules.json")) def _disabled_from_env() -> set[str]: raw = os.getenv("DESK_MODULES_DISABLED", "").strip() if not raw: return set() return {part.strip() for part in raw.split(",") if part.strip()} def _load_overrides() -> dict[str, bool]: if not MODULES_PATH.exists(): return {} try: data = json.loads(MODULES_PATH.read_text(encoding="utf-8")) except (json.JSONDecodeError, OSError): return {} overrides: dict[str, bool] = {} for key, val in data.items(): if isinstance(val, dict) and "enabled" in val: overrides[key] = bool(val["enabled"]) elif isinstance(val, bool): overrides[key] = val return overrides def _save_overrides(overrides: dict[str, bool]) -> None: MODULES_PATH.parent.mkdir(parents=True, exist_ok=True) payload = {mid: {"enabled": overrides[mid]} for mid in overrides if mid in MODULE_BY_ID} MODULES_PATH.write_text(json.dumps(payload, indent=2), encoding="utf-8") def is_module_enabled(module_id: str) -> bool: mod = MODULE_BY_ID.get(module_id) if not mod: return False if mod.locked: return True env_disabled = _disabled_from_env() if module_id in env_disabled: return False overrides = _load_overrides() if module_id in overrides: return overrides[module_id] return mod.default_enabled def set_module_enabled(module_id: str, enabled: bool) -> None: mod = MODULE_BY_ID.get(module_id) if not mod: raise KeyError(f"unknown module: {module_id}") if mod.locked: raise ValueError(f"module {module_id} is locked") overrides = _load_overrides() for m in MODULES: if m.id not in overrides: overrides[m.id] = is_module_enabled(m.id) overrides[module_id] = enabled _save_overrides(overrides) def list_modules() -> list[dict]: items = [] for mod in MODULES: items.append( { "id": mod.id, "label": mod.label, "description": mod.description, "locked": mod.locked, "nav_views": list(mod.nav_views), "enabled": is_module_enabled(mod.id), } ) return items def enabled_nav_views() -> set[str]: views: set[str] = set() for mod in MODULES: if is_module_enabled(mod.id): views.update(mod.nav_views) return views