import json from pathlib import Path from typing import Any, Dict, Optional from .models import CMSProject class CMSManager: def __init__(self, root: Optional[str] = None): self.root = Path( root or Path.cwd() / "storage" / "cms" ) self.root.mkdir(parents=True, exist_ok=True) def _path(self, project_id: str) -> Path: safe = "".join( c if c.isalnum() or c in "-_" else "_" for c in project_id ) if not safe: raise ValueError("project_id is required") return self.root / f"{safe}.json" def get(self, project_id: str) -> Optional[Dict[str, Any]]: path = self._path(project_id) if not path.exists(): return None return json.loads(path.read_text()) def save( self, project_id: str, data: Dict[str, Any] ) -> Dict[str, Any]: project = CMSProject.create( project_id, **data ) path = self._path(project_id) temporary = path.with_suffix(".tmp") temporary.write_text( json.dumps( project.to_dict(), indent=2, ensure_ascii=False ) ) temporary.replace(path) return project.to_dict() def delete(self, project_id: str) -> bool: path = self._path(project_id) if not path.exists(): return False path.unlink() return True _cms_manager: Optional[CMSManager] = None def get_cms_manager() -> CMSManager: global _cms_manager if _cms_manager is None: _cms_manager = CMSManager() return _cms_manager