File size: 2,299 Bytes
67f8819 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | """
Backend configuration with environment variable loading.
Per @specs/001-auth-api-bridge/research.md
"""
import os
from functools import lru_cache
from pathlib import Path
from dotenv import load_dotenv
from pydantic_settings import BaseSettings
from sqlalchemy import create_engine
from sqlmodel import SQLModel
# Load .env file with override to ensure .env takes precedence over system env vars
# This is needed when system env vars are set with placeholder values
env_path = Path(__file__).parent.parent / ".env"
load_dotenv(env_path, override=True)
class Settings(BaseSettings):
"""Application settings loaded from environment variables."""
# Better Auth
better_auth_secret: str
better_auth_url: str = "http://localhost:3000"
# Database
database_url: str
# API
api_port: int = 8000
api_host: str = "localhost"
debug: bool = True
# Chatbot Configuration
# Per @specs/001-chatbot-mcp/plan.md
openai_api_key: str
neon_database_url: str # Same as database_url but explicit for chatbot
mcp_server_port: int = 8000
openai_model: str = "gpt-4-turbo-preview"
mcp_server_host: str = "127.0.0.1"
# Email Configuration
email_host: str = "smtp.gmail.com"
email_port: int = 587
email_username: str = ""
email_password: str = ""
email_from: str = ""
email_from_name: str = "TaskFlow"
emails_enabled: bool = True
class Config:
env_file = ".env"
case_sensitive = False
extra = "ignore" # Ignore extra env vars (frontend vars)
@lru_cache()
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()
# Global settings instance
settings = get_settings()
# Database engine with connection pooling per @specs/001-auth-api-bridge/research.md
engine = create_engine(
settings.database_url,
poolclass=None, # QueuePool (default)
pool_size=5, # Connections to maintain
max_overflow=10, # Additional connections under load
pool_pre_ping=True, # Validate connections before use (handles Neon scale-to-zero)
pool_recycle=3600, # Recycle connections after 1 hour
echo=settings.debug, # Log SQL in development
)
def init_db():
"""Initialize database tables."""
SQLModel.metadata.create_all(engine)
|