feat: Migrate to MySQL and add unified environment configuration
## Database Migration (SQLite → MySQL) - Add Alembic migration framework - Add 'tr_' prefix to all tables to avoid conflicts in shared database - Remove SQLite support, use MySQL exclusively - Add pymysql driver dependency - Change ad_token column to Text type for long JWT tokens ## Unified Environment Configuration - Centralize all hardcoded settings to environment variables - Backend: Extend Settings class in app/core/config.py - Frontend: Use Vite environment variables (import.meta.env) - Docker: Move credentials to environment variables - Update .env.example files with comprehensive documentation ## Test Organization - Move root-level test files to tests/ directory: - test_chat_room.py → tests/test_chat_room.py - test_websocket.py → tests/test_websocket.py - test_realtime_implementation.py → tests/test_realtime_implementation.py - Fix path references in test_realtime_implementation.py Breaking Changes: - CORS now requires explicit origins (no more wildcard) - All database tables renamed with 'tr_' prefix - SQLite no longer supported 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,56 @@
|
||||
# Frontend Environment Variables
|
||||
# =============================================================================
|
||||
# Task Reporter - Frontend Environment Configuration
|
||||
# =============================================================================
|
||||
# Copy this file to .env and customize as needed.
|
||||
# All variables are optional and have sensible defaults for development.
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# API Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
# API Base URL (optional)
|
||||
# - For local development: leave empty or don't set (will use /api)
|
||||
# - For local development: leave empty or don't set (will use /api with proxy)
|
||||
# - For production with separate backend: set to full URL
|
||||
# Example: https://api.yourdomain.com/api
|
||||
VITE_API_BASE_URL=
|
||||
|
||||
# Note: When set, this URL is also used for WebSocket connections
|
||||
# http:// will be converted to ws://
|
||||
# https:// will be converted to wss://
|
||||
# API request timeout in milliseconds (default: 30000 = 30 seconds)
|
||||
VITE_API_TIMEOUT_MS=30000
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Development Server Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
# Frontend development server port (default: 3000)
|
||||
VITE_PORT=3000
|
||||
|
||||
# Backend API URL for development proxy (default: http://localhost:8000)
|
||||
# This is used by Vite's proxy configuration during development
|
||||
VITE_BACKEND_URL=http://localhost:8000
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# WebSocket Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
# Maximum WebSocket reconnection delay in milliseconds (default: 30000 = 30 seconds)
|
||||
# The reconnection uses exponential backoff, capped at this value
|
||||
VITE_MAX_RECONNECT_DELAY_MS=30000
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Query/Cache Configuration
|
||||
# -----------------------------------------------------------------------------
|
||||
# Messages refetch interval in milliseconds (default: 30000 = 30 seconds)
|
||||
# Used for polling online users status
|
||||
VITE_MESSAGES_REFETCH_INTERVAL_MS=30000
|
||||
|
||||
# Reports stale time in milliseconds (default: 30000 = 30 seconds)
|
||||
# Time before cached report data is considered stale
|
||||
VITE_REPORTS_STALE_TIME_MS=30000
|
||||
|
||||
# =============================================================================
|
||||
# Notes
|
||||
# =============================================================================
|
||||
# - All VITE_ prefixed variables are exposed to the browser
|
||||
# - Never put sensitive data (API keys, secrets) in frontend environment variables
|
||||
# - When VITE_API_BASE_URL is set:
|
||||
# - http:// URLs will be converted to ws:// for WebSocket connections
|
||||
# - https:// URLs will be converted to wss:// for WebSocket connections
|
||||
# =============================================================================
|
||||
|
||||
@@ -61,12 +61,18 @@ export function useCreateMessage(roomId: string) {
|
||||
})
|
||||
}
|
||||
|
||||
// Configurable refetch interval for online users (default 30 seconds)
|
||||
const MESSAGES_REFETCH_INTERVAL = parseInt(
|
||||
import.meta.env.VITE_MESSAGES_REFETCH_INTERVAL_MS || '30000',
|
||||
10
|
||||
)
|
||||
|
||||
export function useOnlineUsers(roomId: string) {
|
||||
return useQuery({
|
||||
queryKey: messageKeys.online(roomId),
|
||||
queryFn: () => messagesService.getOnlineUsers(roomId),
|
||||
enabled: !!roomId,
|
||||
refetchInterval: 30000, // Refresh every 30 seconds
|
||||
refetchInterval: MESSAGES_REFETCH_INTERVAL,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ const reportKeys = {
|
||||
[...reportKeys.all, 'detail', roomId, reportId] as const,
|
||||
}
|
||||
|
||||
// Configurable stale time for reports (default 30 seconds)
|
||||
const REPORTS_STALE_TIME = parseInt(
|
||||
import.meta.env.VITE_REPORTS_STALE_TIME_MS || '30000',
|
||||
10
|
||||
)
|
||||
|
||||
/**
|
||||
* Hook to list reports for a room
|
||||
*/
|
||||
@@ -22,7 +28,7 @@ export function useReports(roomId: string) {
|
||||
queryKey: reportKeys.list(roomId),
|
||||
queryFn: () => reportsService.listReports(roomId),
|
||||
enabled: !!roomId,
|
||||
staleTime: 30000, // 30 seconds
|
||||
staleTime: REPORTS_STALE_TIME,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ import type {
|
||||
} from '../types'
|
||||
|
||||
const RECONNECT_DELAY = 1000
|
||||
const MAX_RECONNECT_DELAY = 30000
|
||||
const MAX_RECONNECT_DELAY = parseInt(
|
||||
import.meta.env.VITE_MAX_RECONNECT_DELAY_MS || '30000',
|
||||
10
|
||||
)
|
||||
const RECONNECT_MULTIPLIER = 2
|
||||
|
||||
interface UseWebSocketOptions {
|
||||
|
||||
@@ -3,10 +3,13 @@ import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios'
|
||||
// API Base URL: use environment variable or default to relative path
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api'
|
||||
|
||||
// API Timeout: configurable via environment variable (default 30 seconds)
|
||||
const API_TIMEOUT = parseInt(import.meta.env.VITE_API_TIMEOUT_MS || '30000', 10)
|
||||
|
||||
// Create axios instance
|
||||
const api = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 30000,
|
||||
timeout: API_TIMEOUT,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
|
||||
@@ -1,28 +1,36 @@
|
||||
/// <reference types="vitest/config" />
|
||||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
react(),
|
||||
],
|
||||
server: {
|
||||
port: 3000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8000',
|
||||
changeOrigin: true,
|
||||
ws: true, // Enable WebSocket proxying
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
|
||||
// Configuration from environment variables with defaults
|
||||
const PORT = parseInt(env.VITE_PORT || '3000', 10)
|
||||
const BACKEND_URL = env.VITE_BACKEND_URL || 'http://localhost:8000'
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
tailwindcss(),
|
||||
react(),
|
||||
],
|
||||
server: {
|
||||
port: PORT,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: BACKEND_URL,
|
||||
changeOrigin: true,
|
||||
ws: true, // Enable WebSocket proxying
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: ['./src/test/setup.ts'],
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: ['./src/test/setup.ts'],
|
||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user