#!/usr/bin/env bash set -Eeuo pipefail ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" API_PID="" SECRETARY_PID="" WEB_PID="" die() { echo "[dev-local] $*" >&2 exit 1 } require_command() { command -v "$1" >/dev/null 2>&1 || die "'$1' command not found" } ensure_port_free() { local port="$1" if lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1; then echo "[dev-local] port $port is already in use:" >&2 lsof -nP -iTCP:"$port" -sTCP:LISTEN >&2 || true die "stop the process using port $port, then rerun the local server" fi } wait_for_url() { local name="$1" local url="$2" local attempts=90 echo "[dev-local] waiting for $name..." for ((attempt = 1; attempt <= attempts; attempt++)); do if curl -fsS --max-time 2 "$url" >/dev/null 2>&1; then echo "[dev-local] $name is ready" return 0 fi sleep 1 done die "$name did not respond at $url within ${attempts}s" } cleanup() { local status=$? trap - EXIT INT TERM for pid in "$WEB_PID" "$SECRETARY_PID" "$API_PID"; do if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then kill "$pid" 2>/dev/null || true fi done wait 2>/dev/null || true exit "$status" } require_command curl require_command lsof require_command pnpm [[ -x "$ROOT_DIR/apps/secretary-api/.venv/bin/uvicorn" ]] || \ die "Secretary API virtualenv is missing: apps/secretary-api/.venv/bin/uvicorn" ensure_port_free 3100 ensure_port_free 4000 ensure_port_free 8010 trap cleanup EXIT INT TERM ( cd "$ROOT_DIR/apps/api" APP_ADDRESS=127.0.0.1 pnpm dev ) & API_PID=$! ( cd "$ROOT_DIR/apps/secretary-api" ./.venv/bin/uvicorn app.main:app --reload --host 127.0.0.1 --port 8010 ) & SECRETARY_PID=$! ( cd "$ROOT_DIR/apps/web" pnpm dev --hostname 127.0.0.1 --port 3100 ) & WEB_PID=$! wait_for_url "API" "http://127.0.0.1:4000/api/health" wait_for_url "Secretary API" "http://127.0.0.1:8010/api/health" wait_for_url "Web" "http://127.0.0.1:3100/" echo "[dev-local] all local servers are ready" echo "API: http://127.0.0.1:4000" echo "Secretary API: http://127.0.0.1:8010" echo "Web: http://127.0.0.1:3100" echo "Press Ctrl-C to stop all development servers." wait -n "$API_PID" "$SECRETARY_PID" "$WEB_PID"