#!/usr/bin/env bash # Local bring-up for ecomm (SD-0001 PUC-10). From a clean checkout this: # 1. starts the dev Postgres container and waits for it to be healthy (owns its # lifecycle — Docker is the one prerequisite, docs/BOOTSTRAP.md); # 2. ensures the backend venv + deps and the frontend node_modules; # 3. runs the FastAPI backend (:8000, self-migrating an empty DB) and the Vite dev # server (:5173, proxying /api -> :8000) together. # Ctrl-C stops both processes; the container keeps running (stop it with # `docker compose down`, or `docker compose down -v` to reset to empty). set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$repo_root" export ECOMM_DATABASE_URL="${ECOMM_DATABASE_URL:-postgresql://ecomm:ecomm@localhost:5432/ecomm}" echo "==> dev Postgres (docker compose up --wait)" docker compose up -d --wait db if [ ! -x "$repo_root/.venv/bin/python" ]; then echo "==> creating backend venv" python3 -m venv "$repo_root/.venv" "$repo_root/.venv/bin/python" -m pip install --upgrade pip "$repo_root/.venv/bin/python" -m pip install -r "$repo_root/backend/requirements.txt" fi if [ ! -d "$repo_root/frontend/node_modules" ]; then echo "==> installing frontend deps" ( cd "$repo_root/frontend" && npm install ) fi echo "==> starting backend (:8000) and Vite (:5173) — Ctrl-C to stop" "$repo_root/.venv/bin/python" -m uvicorn app.main:app --app-dir "$repo_root/backend" --port 8000 --reload & backend_pid=$! ( cd "$repo_root/frontend" && npm run dev ) & frontend_pid=$! # Kill a process and its whole descendant tree (children first), portably across # macOS and Linux — npm spawns vite as a grandchild, so killing the captured pid # alone would orphan it on :5173. `pgrep -P` (list children) exists on both. kill_tree() { local pid=$1 child for child in $(pgrep -P "$pid" 2>/dev/null); do kill_tree "$child" done kill "$pid" 2>/dev/null || true } cleanup() { trap - INT TERM echo echo "==> stopping backend and Vite" kill_tree "$backend_pid" kill_tree "$frontend_pid" wait "$backend_pid" "$frontend_pid" 2>/dev/null || true } trap cleanup INT TERM # Wait until either process exits, then tear the other down. `wait -n` would be # tidier but is unsupported on macOS's bundled bash 3.2, so poll portably. while kill -0 "$backend_pid" 2>/dev/null && kill -0 "$frontend_pid" 2>/dev/null; do sleep 1 done cleanup