Add FastAPI backend and React frontend subprojects
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)
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user