Initial commit: WealthWise financial analytics platform

This commit is contained in:
2026-02-14 21:16:57 +05:30
commit b8588df583
171 changed files with 29048 additions and 0 deletions

129
backend/app/core/config.py Normal file
View File

@@ -0,0 +1,129 @@
"""WealthWise application configuration management.
This module provides centralized configuration management using Pydantic Settings v2.
Configuration values are loaded from environment variables and .env files.
"""
from functools import lru_cache
from typing import Any, Optional, Union
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""Application settings management.
All configuration values are loaded from environment variables.
The .env file is automatically loaded when present.
System environment variables override values in .env.
Attributes:
PROJECT_NAME: Application name for documentation and logging
API_V1_STR: Base path for API v1 endpoints
VERSION: Application version string
DATABASE_URL: PostgreSQL connection string (Supabase Transaction Pooler format)
SUPABASE_JWT_SECRET: JWT secret for Supabase authentication
DEBUG: Enable debug mode (default: False)
CORS_ORIGINS: Comma-separated list of allowed CORS origins
"""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore", # Allow extra env vars without raising errors
case_sensitive=True,
)
# Application Info
PROJECT_NAME: str = Field(default="WealthWise", description="Application name")
API_V1_STR: str = Field(default="/api/v1", description="API v1 base path")
VERSION: str = Field(default="1.0.0", description="Application version")
# Security
SECRET_KEY: str = Field(
default="dev-secret-key-change-in-production",
description="Secret key for JWT signing",
)
ALGORITHM: str = Field(
default="HS256",
description="JWT signing algorithm",
)
ACCESS_TOKEN_EXPIRE_MINUTES: int = Field(
default=30,
description="JWT token expiration in minutes",
)
# Database - Local PostgreSQL (Docker)
DATABASE_URL: str = Field(
default="postgresql+asyncpg://postgres:postgres@localhost:5432/wealthwise",
description="PostgreSQL async connection string",
)
# Database Pool Configuration
DB_POOL_SIZE: int = Field(default=20, ge=1, le=100, description="Connection pool size")
DB_MAX_OVERFLOW: int = Field(default=10, ge=0, le=50, description="Max overflow connections")
DB_POOL_PRE_PING: bool = Field(
default=True,
description="Verify connections before using from pool",
)
DB_ECHO: bool = Field(default=False, description="Echo SQL queries to stdout")
# API Configuration
DEBUG: bool = Field(default=False, description="Debug mode")
CORS_ORIGINS: str = Field(
default="http://localhost:5173,http://localhost:3000",
description="Comma-separated list of allowed CORS origins",
)
# Logging
LOG_LEVEL: str = Field(default="INFO", pattern="^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$")
@property
def cors_origins_list(self) -> list[str]:
"""Parse CORS_ORIGINS string into a list.
Returns:
List of origin strings
"""
return [origin.strip() for origin in self.CORS_ORIGINS.split(",") if origin.strip()]
@field_validator("DATABASE_URL")
@classmethod
def validate_database_url(cls, v: Optional[str]) -> Any:
"""Validate and ensure proper asyncpg driver in DATABASE_URL.
Args:
v: Database URL string
Returns:
Validated database URL with asyncpg driver
Raises:
ValueError: If URL format is invalid
"""
if not v:
raise ValueError("DATABASE_URL cannot be empty")
# Ensure asyncpg driver is used
if v.startswith("postgresql://"):
v = v.replace("postgresql://", "postgresql+asyncpg://", 1)
elif not v.startswith("postgresql+asyncpg://"):
raise ValueError(
"DATABASE_URL must use postgresql+asyncpg:// driver for async support"
)
return v
@lru_cache()
def get_settings() -> Settings:
"""Get cached settings instance.
This function uses LRU caching to avoid re-reading configuration
on every call. Settings are loaded once at application startup.
Returns:
Settings instance with all configuration values
"""
return Settings()