Files
cad-Integration/CADDesigner-Code-main/start_caddesigner_ui.py
T
2026-07-22 13:48:46 +08:00

176 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""
CADDesigner React Web UI startup script.
"""
import argparse
import os
from pathlib import Path
import shutil
import subprocess
import sys
project_root = Path(__file__).parent
frontend_root = project_root / "frontend"
def resolve_browser_host(host: str) -> str:
"""Convert a bind address to a display address better suited for browser access."""
if host in {"0.0.0.0", "::"}:
return "localhost"
return host
def resolve_api_url(api_url: str | None) -> str:
"""Resolve the API address that the React UI should connect to."""
if api_url:
return api_url.rstrip("/")
env_api_url = os.getenv("CADDESIGNER_API_URL")
if env_api_url:
return env_api_url.rstrip("/")
return "http://127.0.0.1:8000"
def resolve_package_manager() -> tuple[str, str]:
"""Prefer pnpm, then fall back to npm."""
pnpm_cmd = shutil.which("pnpm")
if pnpm_cmd:
return pnpm_cmd, "pnpm"
npm_cmd = shutil.which("npm")
if npm_cmd:
return npm_cmd, "npm"
raise RuntimeError("Neither pnpm nor npm was found. Please install a Node.js package manager first.")
def ensure_frontend_ready(debug: bool = False) -> tuple[str, str]:
"""Ensure React frontend dependencies are ready and return package manager information."""
if not frontend_root.is_dir():
raise RuntimeError(f"React frontend directory does not exist: {frontend_root}")
package_manager_cmd, package_manager_name = resolve_package_manager()
if not (frontend_root / "node_modules").exists():
print(
f"React frontend dependencies are not installed yet; running {package_manager_name} install ..."
)
install_result = subprocess.run(
[package_manager_cmd, "install"],
cwd=frontend_root,
)
if install_result.returncode != 0:
raise RuntimeError(
f"{package_manager_name} install failed; unable to start React UI"
)
if debug:
print("React frontend dependencies installed successfully")
return package_manager_cmd, package_manager_name
def launch_react_app(args) -> None:
"""Start the standalone React Web UI (Vite)."""
package_manager_cmd, package_manager_name = ensure_frontend_ready(debug=args.debug)
api_url = resolve_api_url(args.api_url)
display_host = resolve_browser_host(args.host)
env = os.environ.copy()
env["VITE_API_BASE_URL"] = api_url
env["CADDESIGNER_API_PROXY_TARGET"] = api_url
print("Starting CADDesigner React Web UI...")
print("=" * 60)
print(f"React UI address: http://{display_host}:{args.port}")
print(f"API proxy target: {api_url}")
print(f"Frontend package manager: {package_manager_name}")
print(f"Frontend directory: {frontend_root}")
if args.debug:
print("Debug mode: enabled")
print("Press Ctrl+C to stop the service")
print("=" * 60)
extra_args_separator = ["--"] if package_manager_name == "npm" else []
cmd = [
package_manager_cmd,
"run",
"dev",
*extra_args_separator,
"--host",
args.host,
"--port",
str(args.port),
"--strictPort",
]
os.chdir(frontend_root)
os.execvpe(package_manager_cmd, cmd, env)
def main():
"""Main function."""
parser = argparse.ArgumentParser(
description="CADDesigner React Web UI launcher",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Usage examples:
# Start React UI with the default configuration
%(prog)s
# Customize the listening address
%(prog)s --host 0.0.0.0 --port 7861
# Connect to a remote API server; React forwards requests through the proxy
%(prog)s --api-url http://192.168.1.100:8000
Environment variable:
CADDESIGNER_API_URL API server address (default: http://localhost:8000)
""",
)
parser.add_argument(
"--host",
default="0.0.0.0",
help="Web UI server host address (default: 0.0.0.0)",
)
parser.add_argument(
"--port",
type=int,
default=7860,
help="Web UI server port (default: 7860)",
)
parser.add_argument(
"--api-url",
default=None,
help="CADDesigner API server address (default: http://localhost:8000)",
)
parser.add_argument(
"--debug",
action="store_true",
help="Enable debug mode",
)
args = parser.parse_args()
try:
launch_react_app(args)
except KeyboardInterrupt:
print("\nUser canceled; exiting...")
except Exception as exc:
print(f"Startup failed: {exc}")
if args.debug:
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()