- Add SQLite as alternative database for offline/firewall environments - Add --database-type parameter to build-client.bat (mysql/sqlite) - Refactor database.py to support both MySQL and SQLite - Add DB_TYPE and SQLITE_PATH configuration options - Set fixed unpackDirName for portable exe (Meeting-Assistant) - Update DEPLOYMENT.md with SQLite mode documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
166 lines
5.6 KiB
Python
166 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Backend entry point for embedded deployment.
|
|
Loads configuration from config.json and starts uvicorn server.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
|
|
|
|
def get_base_dir() -> str:
|
|
"""Get base directory, supporting PyInstaller frozen executables."""
|
|
if getattr(sys, "frozen", False):
|
|
# Running as PyInstaller bundle
|
|
return os.path.dirname(sys.executable)
|
|
else:
|
|
# Running as script
|
|
return os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def load_config(config_path: str | None = None) -> dict:
|
|
"""Load configuration from config.json file."""
|
|
if config_path is None:
|
|
base_dir = get_base_dir()
|
|
config_path = os.path.join(base_dir, "config.json")
|
|
|
|
if os.path.exists(config_path):
|
|
# Use utf-8-sig to handle Windows BOM (Byte Order Mark)
|
|
with open(config_path, "r", encoding="utf-8-sig") as f:
|
|
return json.load(f)
|
|
return {}
|
|
|
|
|
|
def apply_config_to_env(config: dict) -> None:
|
|
"""
|
|
Apply config.json values to environment variables.
|
|
Environment variables take precedence (already set values are not overwritten).
|
|
"""
|
|
backend_config = config.get("backend", {})
|
|
|
|
# Server configuration
|
|
if "host" in backend_config:
|
|
os.environ.setdefault("BACKEND_HOST", backend_config["host"])
|
|
if "port" in backend_config:
|
|
os.environ.setdefault("BACKEND_PORT", str(backend_config["port"]))
|
|
|
|
# Database configuration - use direct assignment to ensure config values are used
|
|
db_config = backend_config.get("database", {})
|
|
if "type" in db_config:
|
|
os.environ["DB_TYPE"] = db_config["type"]
|
|
if "sqlitePath" in db_config:
|
|
os.environ["SQLITE_PATH"] = db_config["sqlitePath"]
|
|
if "host" in db_config:
|
|
os.environ["DB_HOST"] = db_config["host"]
|
|
if "port" in db_config:
|
|
os.environ["DB_PORT"] = str(db_config["port"])
|
|
if "user" in db_config:
|
|
os.environ["DB_USER"] = db_config["user"]
|
|
if "password" in db_config:
|
|
os.environ["DB_PASS"] = db_config["password"]
|
|
if "database" in db_config:
|
|
os.environ["DB_NAME"] = db_config["database"]
|
|
if "poolSize" in db_config:
|
|
os.environ["DB_POOL_SIZE"] = str(db_config["poolSize"])
|
|
|
|
# External API configuration - use direct assignment
|
|
api_config = backend_config.get("externalApis", {})
|
|
if "authApiUrl" in api_config:
|
|
os.environ["AUTH_API_URL"] = api_config["authApiUrl"]
|
|
if "difyApiUrl" in api_config:
|
|
os.environ["DIFY_API_URL"] = api_config["difyApiUrl"]
|
|
if "difyApiKey" in api_config:
|
|
os.environ["DIFY_API_KEY"] = api_config["difyApiKey"]
|
|
if "difySttApiKey" in api_config:
|
|
os.environ["DIFY_STT_API_KEY"] = api_config["difySttApiKey"]
|
|
|
|
# Authentication configuration - use direct assignment
|
|
auth_config = backend_config.get("auth", {})
|
|
if "adminEmail" in auth_config:
|
|
os.environ["ADMIN_EMAIL"] = auth_config["adminEmail"]
|
|
if "jwtSecret" in auth_config:
|
|
os.environ["JWT_SECRET"] = auth_config["jwtSecret"]
|
|
if "jwtExpireHours" in auth_config:
|
|
os.environ["JWT_EXPIRE_HOURS"] = str(auth_config["jwtExpireHours"])
|
|
|
|
# File configuration - set TEMPLATE_DIR and RECORD_DIR relative to base
|
|
base_dir = get_base_dir()
|
|
if not os.environ.get("TEMPLATE_DIR"):
|
|
template_dir = os.path.join(base_dir, "template")
|
|
if os.path.exists(template_dir):
|
|
os.environ["TEMPLATE_DIR"] = template_dir
|
|
|
|
if not os.environ.get("RECORD_DIR"):
|
|
record_dir = os.path.join(base_dir, "record")
|
|
os.makedirs(record_dir, exist_ok=True)
|
|
os.environ["RECORD_DIR"] = record_dir
|
|
|
|
|
|
def main():
|
|
"""Main entry point."""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description="Meeting Assistant Backend Server")
|
|
parser.add_argument(
|
|
"--config",
|
|
type=str,
|
|
help="Path to config.json file",
|
|
)
|
|
parser.add_argument(
|
|
"--host",
|
|
type=str,
|
|
help="Host to bind to (overrides config)",
|
|
)
|
|
parser.add_argument(
|
|
"--port",
|
|
type=int,
|
|
help="Port to bind to (overrides config)",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
# Load and apply configuration
|
|
config = load_config(args.config)
|
|
|
|
# Debug: print loaded config
|
|
print(f"DEBUG: Config path: {args.config}", flush=True)
|
|
print(f"DEBUG: Loaded config keys: {list(config.keys())}", flush=True)
|
|
backend_config = config.get("backend", {})
|
|
db_config = backend_config.get("database", {})
|
|
print(f"DEBUG: DB type={db_config.get('type', 'mysql')}", flush=True)
|
|
print(f"DEBUG: DB config: host={db_config.get('host')}, user={db_config.get('user')}, pass={'***' if db_config.get('password') else 'EMPTY'}", flush=True)
|
|
|
|
apply_config_to_env(config)
|
|
|
|
# Debug: print env vars after setting
|
|
print(f"DEBUG: ENV DB_TYPE={os.environ.get('DB_TYPE', 'mysql')}", flush=True)
|
|
print(f"DEBUG: ENV DB_HOST={os.environ.get('DB_HOST')}", flush=True)
|
|
print(f"DEBUG: ENV DB_USER={os.environ.get('DB_USER')}", flush=True)
|
|
print(f"DEBUG: ENV DB_PASS={'***' if os.environ.get('DB_PASS') else 'EMPTY'}", flush=True)
|
|
|
|
# Command line arguments override everything
|
|
if args.host:
|
|
os.environ["BACKEND_HOST"] = args.host
|
|
if args.port:
|
|
os.environ["BACKEND_PORT"] = str(args.port)
|
|
|
|
# Get final host/port values
|
|
host = os.environ.get("BACKEND_HOST", "127.0.0.1")
|
|
port = int(os.environ.get("BACKEND_PORT", "8000"))
|
|
|
|
print(f"Starting backend server on {host}:{port}", flush=True)
|
|
|
|
# Import and run uvicorn
|
|
import uvicorn
|
|
|
|
uvicorn.run(
|
|
"app.main:app",
|
|
host=host,
|
|
port=port,
|
|
log_level="info",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|