3c432473e5
Backend: - FastAPI app with 17 REST endpoints covering dashboard, monitoring, media index, file browser, and jobs - Reuses existing clients/domain/services unchanged - pydantic-settings config, dependency injection, CORS setup - Auto-generated OpenAPI docs at /docs Frontend: - Vite + React + TypeScript SPA - @tanstack/react-query for data fetching with polling - ag-grid-react for media table and file browser - recharts for monitoring charts - Tailwind CSS styling - 4 pages: Dashboard, Monitoring, Media, File Browser - Typed API client matching all backend endpoints Also: - docs/MIGRATION_PLAN.md with full architecture plan - Updated .gitignore for both subprojects - Streamlit app preserved for now (can coexist)
64 lines
1.5 KiB
Python
64 lines
1.5 KiB
Python
"""Backend configuration using pydantic-settings.
|
|
|
|
Reads from environment variables and .env file automatically.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
|
class JellyfinSettings(BaseSettings):
|
|
url: str = ""
|
|
api_key: str = ""
|
|
user_id: str = ""
|
|
|
|
model_config = {"env_prefix": "JELLYFIN_"}
|
|
|
|
|
|
class SSHSettings(BaseSettings):
|
|
host: str = ""
|
|
username: str = ""
|
|
port: int = 22
|
|
key_filename: str = str(Path.home() / ".ssh" / "id_rsa")
|
|
password: str = ""
|
|
media_root: str = ""
|
|
path_prefix: str = ""
|
|
|
|
model_config = {"env_prefix": "SSH_"}
|
|
|
|
|
|
class RemoteSettings(BaseSettings):
|
|
"""Extra remote settings that don't fit the SSH_ prefix."""
|
|
|
|
media_root: str = ""
|
|
path_prefix: str = ""
|
|
|
|
model_config = {"env_prefix": "REMOTE_"}
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Top-level application settings."""
|
|
|
|
jellyfin: JellyfinSettings = JellyfinSettings()
|
|
ssh: SSHSettings = SSHSettings()
|
|
remote: RemoteSettings = RemoteSettings()
|
|
|
|
# Derived convenience properties
|
|
@property
|
|
def media_root(self) -> str:
|
|
return self.remote.media_root or self.ssh.media_root or ""
|
|
|
|
@property
|
|
def path_prefix(self) -> str:
|
|
return self.remote.path_prefix or self.ssh.path_prefix or ""
|
|
|
|
model_config = {"env_file": ".env", "env_file_encoding": "utf-8", "extra": "ignore"}
|
|
|
|
|
|
def get_settings() -> Settings:
|
|
"""Create a Settings instance (reads env/.env on each call)."""
|
|
return Settings()
|