from __future__ import annotations from functools import lru_cache from os import environ from pathlib import Path from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict SERVER_DIR = Path(__file__).resolve().parents[3] ROOT_DIR = SERVER_DIR.parent class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=(ROOT_DIR / ".env", SERVER_DIR / ".env"), env_file_encoding="utf-8", extra="ignore", ) app_name: str = Field(default="X-Financial Server", alias="APP_NAME") app_env: str = Field(default="local", alias="APP_ENV") app_debug: bool = Field(default=True, alias="APP_DEBUG") setup_completed: bool = Field(default=False, alias="SETUP_COMPLETED") company_name: str = Field(default="", alias="COMPANY_NAME") company_code: str = Field(default="", alias="COMPANY_CODE") admin_email: str = Field(default="", alias="ADMIN_EMAIL") web_host: str = Field(default="0.0.0.0", alias="WEB_HOST") web_port: int = Field(default=5173, alias="WEB_PORT") app_host: str = Field(default="0.0.0.0", alias="SERVER_HOST") app_port: int = Field(default=8000, alias="SERVER_PORT") api_v1_prefix: str = Field(default="/api/v1", alias="API_V1_PREFIX") postgres_host: str = Field(default="127.0.0.1", alias="POSTGRES_HOST") postgres_port: int = Field(default=5432, alias="POSTGRES_PORT") postgres_db: str = Field(default="x_financial", alias="POSTGRES_DB") postgres_user: str = Field(default="postgres", alias="POSTGRES_USER") postgres_password: str = Field(default="postgres", alias="POSTGRES_PASSWORD") database_url: str | None = Field(default=None, alias="DATABASE_URL") sqlalchemy_echo: bool = Field(default=False, alias="SQLALCHEMY_ECHO") redis_url: str | None = Field(default=None, alias="REDIS_URL") cors_origins: list[str] = Field(default_factory=list, alias="CORS_ORIGINS") vite_api_base_url: str = Field( default="http://127.0.0.1:8000/api/v1", alias="VITE_API_BASE_URL" ) log_level: str = Field(default="INFO", alias="LOG_LEVEL") log_dir: str = Field(default="logs", alias="LOG_DIR") log_file_enabled: bool = Field(default=True, alias="LOG_FILE_ENABLED") storage_root_dir: str = Field(default="storage", alias="STORAGE_ROOT_DIR") @property def resolved_database_url(self) -> str: if self.database_url: return self.database_url return ( f"postgresql+psycopg://{self.postgres_user}:{self.postgres_password}" f"@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}" ) @property def resolved_storage_root_dir(self) -> Path: path = Path(self.storage_root_dir) if not path.is_absolute(): path = SERVER_DIR / path return path.resolve() @lru_cache def get_settings() -> Settings: return Settings() def refresh_settings(updated_values: dict[str, str]) -> Settings: for key, value in updated_values.items(): environ[key] = value get_settings.cache_clear() return get_settings()