diff --git a/README.md b/README.md index 9c396971..d290676a 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,8 @@ Run both application services from the repository root with: ./run.sh ``` -The startup script expects `backend/app/main.py` and -`frontend/package.json` to be added by the implementation phase. +On Windows, run `run.bat` instead. + +Python 3 and Node.js (including npm) must be installed first. Both startup +scripts create `backend/.venv` and install the backend and frontend +dependencies automatically when they are missing. diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts index 9edff1c7..c4b7818f 100644 --- a/frontend/next-env.d.ts +++ b/frontend/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/run.bat b/run.bat new file mode 100644 index 00000000..b6393e08 --- /dev/null +++ b/run.bat @@ -0,0 +1,94 @@ +@echo off +setlocal EnableExtensions + +set "ROOT_DIR=%~dp0" +set "BACKEND_HOST=%BACKEND_HOST%" +set "BACKEND_PORT=%BACKEND_PORT%" +set "FRONTEND_HOST=%FRONTEND_HOST%" +set "FRONTEND_PORT=%FRONTEND_PORT%" + +if not defined BACKEND_HOST set "BACKEND_HOST=127.0.0.1" +if not defined BACKEND_PORT set "BACKEND_PORT=8000" +if not defined FRONTEND_HOST set "FRONTEND_HOST=127.0.0.1" +if not defined FRONTEND_PORT set "FRONTEND_PORT=5173" +if not defined PYTHON_BIN set "PYTHON_BIN=python" + +call "%PYTHON_BIN%" --version >nul 2>&1 +if errorlevel 1 ( + if /i "%PYTHON_BIN%"=="python" ( + call py --version >nul 2>&1 + if not errorlevel 1 set "PYTHON_BIN=py" + ) +) +set "BACKEND_VENV=%ROOT_DIR%backend\.venv" +set "BACKEND_PYTHON=%BACKEND_VENV%\Scripts\python.exe" + +if not exist "%ROOT_DIR%backend\app\main.py" ( + echo Backend entrypoint not found: backend\app\main.py + exit /b 1 +) + +if not exist "%ROOT_DIR%frontend\package.json" ( + echo Frontend package manifest not found: frontend\package.json + exit /b 1 +) + +if not exist "%ROOT_DIR%backend\requirements.txt" ( + echo Backend requirements not found: backend\requirements.txt + exit /b 1 +) + +call "%PYTHON_BIN%" --version >nul 2>&1 +if errorlevel 1 ( + echo Python executable not found: %PYTHON_BIN% + echo Set PYTHON_BIN to the Python executable path and run this script again. + exit /b 1 +) + +where npm >nul 2>&1 +if errorlevel 1 ( + echo npm is required to start the frontend. + exit /b 1 +) + +if not exist "%BACKEND_PYTHON%" ( + echo Creating backend virtual environment... + call "%PYTHON_BIN%" -m venv "%BACKEND_VENV%" + if errorlevel 1 exit /b 1 +) + +call "%BACKEND_PYTHON%" -c "import build123d, dotenv, fastapi, httpx, jsonschema, multipart, uvicorn" >nul 2>&1 +if errorlevel 1 ( + echo Installing backend dependencies... + call "%BACKEND_PYTHON%" -m pip install -r "%ROOT_DIR%backend\requirements.txt" + if errorlevel 1 exit /b 1 +) + +if not exist "%ROOT_DIR%frontend\node_modules\next" ( + echo Installing frontend dependencies... + pushd "%ROOT_DIR%frontend" + if exist package-lock.json ( + call npm ci + ) else ( + call npm install + ) + if errorlevel 1 ( + popd + exit /b 1 + ) + popd +) + +echo Starting backend on %BACKEND_HOST%:%BACKEND_PORT% +start "CAD CDSL Backend" /D "%ROOT_DIR%backend" cmd /k call "%BACKEND_PYTHON%" -m uvicorn app.main:app --host %BACKEND_HOST% --port %BACKEND_PORT% --reload + +echo Starting frontend on %FRONTEND_HOST%:%FRONTEND_PORT% +start "CAD CDSL Frontend" /D "%ROOT_DIR%frontend" cmd /k call npm run dev -- -H %FRONTEND_HOST% -p %FRONTEND_PORT% + +echo. +echo Frontend: http://%FRONTEND_HOST%:%FRONTEND_PORT% +echo Backend: http://%BACKEND_HOST%:%BACKEND_PORT% +echo The backend and frontend are running in separate command windows. +echo Close those windows to stop the services. + +endlocal diff --git a/run.sh b/run.sh index 6feca844..d45995ad 100755 --- a/run.sh +++ b/run.sh @@ -7,6 +7,8 @@ BACKEND_PORT="${BACKEND_PORT:-8000}" FRONTEND_HOST="${FRONTEND_HOST:-127.0.0.1}" FRONTEND_PORT="${FRONTEND_PORT:-5173}" PYTHON_BIN="${PYTHON_BIN:-python3}" +BACKEND_VENV="${ROOT_DIR}/backend/.venv" +BACKEND_PYTHON="${BACKEND_VENV}/bin/python" cleanup() { local pids @@ -28,6 +30,11 @@ if [[ ! -f "${ROOT_DIR}/frontend/package.json" ]]; then exit 1 fi +if [[ ! -f "${ROOT_DIR}/backend/requirements.txt" ]]; then + echo "Backend requirements not found: backend/requirements.txt" + exit 1 +fi + command -v "${PYTHON_BIN}" >/dev/null 2>&1 || { echo "Python executable not found: ${PYTHON_BIN}" exit 1 @@ -38,10 +45,32 @@ command -v npm >/dev/null 2>&1 || { exit 1 } +if [[ ! -x "${BACKEND_PYTHON}" ]]; then + echo "Creating backend virtual environment..." + "${PYTHON_BIN}" -m venv "${BACKEND_VENV}" +fi + +if ! "${BACKEND_PYTHON}" -c 'import build123d, dotenv, fastapi, httpx, jsonschema, multipart, uvicorn' >/dev/null 2>&1; then + echo "Installing backend dependencies..." + "${BACKEND_PYTHON}" -m pip install -r "${ROOT_DIR}/backend/requirements.txt" +fi + +if [[ ! -d "${ROOT_DIR}/frontend/node_modules/next" ]]; then + echo "Installing frontend dependencies..." + ( + cd "${ROOT_DIR}/frontend" + if [[ -f package-lock.json ]]; then + npm ci + else + npm install + fi + ) +fi + echo "Starting backend on ${BACKEND_HOST}:${BACKEND_PORT}" ( cd "${ROOT_DIR}/backend" - "${PYTHON_BIN}" -m uvicorn app.main:app \ + "${BACKEND_PYTHON}" -m uvicorn app.main:app \ --host "${BACKEND_HOST}" \ --port "${BACKEND_PORT}" \ --reload