#!/bin/bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" BACKEND_DIR="$SCRIPT_DIR/backend" FRONTEND_DIR="$SCRIPT_DIR/frontend" ROOT_ENV="$SCRIPT_DIR/.env" BACKEND_ENV="$BACKEND_DIR/.env" BACKEND_ENV_EXAMPLE="$BACKEND_DIR/.env.example" FRONTEND_ENV_LOCAL="$FRONTEND_DIR/.env.local" HOST_OS="$(uname -s)" USE_WINDOWS_TOOLS=false if command -v cmd.exe >/dev/null 2>&1 || command -v powershell.exe >/dev/null 2>&1; then USE_WINDOWS_TOOLS=true fi if [[ "$USE_WINDOWS_TOOLS" == true ]]; then BACKEND_PYTHON="$BACKEND_DIR/.venv/Scripts/python.exe" FRONTEND_NPM="npm.cmd" else BACKEND_PYTHON="$BACKEND_DIR/.venv/bin/python" FRONTEND_NPM="npm" fi print_header() { echo "==========================================" echo " Jarvis - Setup" echo "==========================================" echo } require_command() { local command_name="$1" local hint="$2" if ! command -v "$command_name" >/dev/null 2>&1; then echo "[ERROR] $command_name was not found." echo "[ERROR] $hint" exit 1 fi } ensure_backend_env() { if [[ -f "$BACKEND_ENV" ]]; then echo "[OK] Backend env file exists: $BACKEND_ENV" return 0 fi if [[ -f "$ROOT_ENV" ]]; then cp "$ROOT_ENV" "$BACKEND_ENV" echo "[INFO] Created backend/.env from root .env" return 0 fi if [[ -f "$BACKEND_ENV_EXAMPLE" ]]; then cp "$BACKEND_ENV_EXAMPLE" "$BACKEND_ENV" echo "[INFO] Created backend/.env from backend/.env.example" echo "[INFO] Edit $BACKEND_ENV before running start.sh if needed." return 0 fi echo "[ERROR] Could not create backend/.env" exit 1 } sync_frontend_env() { local backend_host local backend_port backend_host="$(grep '^HOST=' "$BACKEND_ENV" | cut -d'=' -f2- | tr -d '\r' || true)" backend_port="$(grep '^PORT=' "$BACKEND_ENV" | cut -d'=' -f2- | tr -d '\r' || true)" [[ -z "$backend_host" ]] && backend_host="127.0.0.1" [[ -z "$backend_port" ]] && backend_port="3337" printf 'VITE_API_URL=http://%s:%s\n' "$backend_host" "$backend_port" > "$FRONTEND_ENV_LOCAL" echo "[OK] Synced frontend/.env.local -> http://$backend_host:$backend_port" } print_header require_command npm "Install Node.js and npm first." if [[ "$USE_WINDOWS_TOOLS" == true ]]; then if command -v py.exe >/dev/null 2>&1; then if py.exe -3.13 --version >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("py.exe" "-3.13") elif py.exe -3.12 --version >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("py.exe" "-3.12") elif py.exe -3 --version >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("py.exe" "-3") else echo "[ERROR] Python 3 was not found via py.exe." echo "[ERROR] Install Python 3.12+ for Windows first." exit 1 fi elif command -v python.exe >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("python.exe") elif command -v python >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("python") else echo "[ERROR] Python was not found." echo "[ERROR] Install Python 3.12+ for Windows first." exit 1 fi else if command -v python3 >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("python3") elif command -v python >/dev/null 2>&1; then PYTHON_BOOTSTRAP=("python") else echo "[ERROR] python3/python was not found." echo "[ERROR] Install Python 3.12+ first." exit 1 fi fi install_backend_dependencies() { if command -v uv >/dev/null 2>&1; then echo "[INFO] Using uv to install backend dependencies..." ( cd "$BACKEND_DIR" uv sync ) return 0 fi echo "[INFO] uv was not found. Falling back to venv + pip..." ( cd "$BACKEND_DIR" if ! "${PYTHON_BOOTSTRAP[@]}" -m venv .venv; then echo "[WARN] python -m venv failed. Trying virtualenv fallback..." "${PYTHON_BOOTSTRAP[@]}" -m pip install --user virtualenv "${PYTHON_BOOTSTRAP[@]}" -m virtualenv .venv fi if [[ "$USE_WINDOWS_TOOLS" == true ]]; then .venv/Scripts/python.exe -m pip install --upgrade pip .venv/Scripts/python.exe -m pip install -e . else .venv/bin/python -m pip install --upgrade pip .venv/bin/python -m pip install -e . fi ) } install_frontend_dependencies() { if [[ "$USE_WINDOWS_TOOLS" == true ]]; then ( cd "$FRONTEND_DIR" if [[ -f "package-lock.json" ]]; then cmd.exe /c npm ci else cmd.exe /c npm install fi ) else ( cd "$FRONTEND_DIR" if [[ -f "package-lock.json" ]]; then npm ci else npm install fi ) fi if [[ -f "$FRONTEND_DIR/node_modules/.bin/vite" || -f "$FRONTEND_DIR/node_modules/.bin/vite.cmd" ]]; then return 0 fi echo "[ERROR] Frontend dependencies were installed, but vite was not found." echo "[ERROR] Check frontend/node_modules and npm output." exit 1 } echo "[1/4] Prepare backend environment file..." ensure_backend_env echo echo "[2/4] Install backend dependencies..." install_backend_dependencies if [[ "$USE_WINDOWS_TOOLS" == true ]]; then if [[ ! -f "$BACKEND_PYTHON" ]]; then echo "[ERROR] Backend virtual environment Python was not found after setup: $BACKEND_PYTHON" exit 1 fi else if [[ ! -x "$BACKEND_PYTHON" ]]; then echo "[ERROR] Backend virtual environment Python was not found after setup: $BACKEND_PYTHON" exit 1 fi fi echo "[OK] Backend dependencies installed." echo echo "[3/4] Install frontend dependencies..." install_frontend_dependencies echo "[OK] Frontend dependencies installed." echo echo "[4/4] Sync frontend API configuration..." sync_frontend_env echo echo "==========================================" echo " Setup complete" echo echo " Backend env: $BACKEND_ENV" echo " Frontend env: $FRONTEND_ENV_LOCAL" echo echo " Next: bash start.sh" echo "=========================================="