#!/usr/bin/env bash set -euo pipefail PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" load_local_env() { local env_file for env_file in "${PROJECT_ROOT}/.env" "${PROJECT_ROOT}/.env.local"; do [[ -f "$env_file" ]] || continue while IFS= read -r line || [[ -n "$line" ]]; do [[ -z "$line" || "$line" == \#* || "$line" != *=* ]] && continue local key="${line%%=*}" local value="${line#*=}" [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]] || continue if [[ "$value" == \"*\" && "$value" == *\" ]]; then value="${value:1:${#value}-2}" elif [[ "$value" == \'*\' && "$value" == *\' ]]; then value="${value:1:${#value}-2}" fi export "$key=$value" done < "$env_file" done } load_local_env find_postgres_container() { local candidate compose_container if [[ -n "${AI_GATEWAY_PG_CONTAINER:-}" ]]; then if docker inspect "$AI_GATEWAY_PG_CONTAINER" >/dev/null 2>&1; then printf '%s\n' "$AI_GATEWAY_PG_CONTAINER" return 0 fi return 1 fi for candidate in easyai-pgvector postgres; do if docker inspect "$candidate" >/dev/null 2>&1; then printf '%s\n' "$candidate" return 0 fi done compose_container="$( docker compose -f "${PROJECT_ROOT}/docker-compose.yml" ps -q postgres 2>/dev/null \ | head -n 1 )" if [[ -n "$compose_container" ]] && docker inspect "$compose_container" >/dev/null 2>&1; then printf '%s\n' "$compose_container" return 0 fi return 1 } postgres_host_port() { local mapping port mapping="$(docker port "$1" 5432/tcp 2>/dev/null | head -n 1)" port="${mapping##*:}" if [[ "$port" =~ ^[0-9]+$ ]]; then printf '%s\n' "$port" else printf '5432\n' fi } stop_stale_api_processes() { local api_port="${HTTP_ADDR:-:8088}" api_port="${api_port##*:}" local api_cwd="${PROJECT_ROOT}/apps/api" if command -v pgrep >/dev/null 2>&1; then while read -r pid; do [[ -z "$pid" || "$pid" == "$$" ]] && continue local cwd cwd="$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | awk '/^n/ {print substr($0, 2); exit}')" if [[ "$cwd" == "$api_cwd" ]]; then echo "[ai-gateway] stopping stale go-watch process: ${pid}" kill "$pid" 2>/dev/null || true fi done < <(pgrep -f "go-watch\\.mjs -- go run ./cmd/gateway" || true) fi if ! command -v lsof >/dev/null 2>&1; then return fi local pids pids="$(lsof -tiTCP:"$api_port" -sTCP:LISTEN 2>/dev/null || true)" [[ -z "$pids" ]] && return while read -r pid; do [[ -z "$pid" ]] && continue local cwd command cwd="$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | awk '/^n/ {print substr($0, 2); exit}')" command="$(ps -p "$pid" -o command= 2>/dev/null || true)" if [[ "$cwd" == "$api_cwd" || "$command" == *"easyai-ai-gateway"* ]]; then echo "[ai-gateway] freeing API port ${api_port}, stopping stale process: ${pid}" kill "$pid" 2>/dev/null || true else echo "[ai-gateway] port ${api_port} is used by an unrelated process: ${pid} ${command}" >&2 exit 1 fi done <<< "$pids" sleep 0.5 } database_url_was_configured=0 pg_container_was_configured=0 [[ -n "${AI_GATEWAY_DATABASE_URL:-}" ]] && database_url_was_configured=1 [[ -n "${AI_GATEWAY_PG_CONTAINER:-}" ]] && pg_container_was_configured=1 postgres_container="$(find_postgres_container || true)" if [[ -n "$postgres_container" ]]; then export AI_GATEWAY_PG_CONTAINER="$postgres_container" elif [[ "$pg_container_was_configured" == "1" ]]; then echo "[ai-gateway] configured PostgreSQL container is unavailable; using the database URL without Docker database creation" >&2 fi export AI_GATEWAY_PG_USER="${AI_GATEWAY_PG_USER:-easyai}" if [[ -z "${AI_GATEWAY_PG_PASSWORD:-}" && -n "$postgres_container" ]]; then AI_GATEWAY_PG_PASSWORD="$( docker inspect "$postgres_container" --format '{{range .Config.Env}}{{println .}}{{end}}' \ | awk -F= '$1 == "POSTGRES_PASSWORD" {print $2; exit}' )" export AI_GATEWAY_PG_PASSWORD fi export AI_GATEWAY_PG_PASSWORD="${AI_GATEWAY_PG_PASSWORD:-easyai2025}" export AI_GATEWAY_DATABASE_NAME="${AI_GATEWAY_DATABASE_NAME:-easyai_ai_gateway}" if [[ "$database_url_was_configured" == "0" ]]; then postgres_port=5432 if [[ -n "$postgres_container" ]]; then postgres_port="$(postgres_host_port "$postgres_container")" fi export AI_GATEWAY_DATABASE_URL="postgresql://${AI_GATEWAY_PG_USER}:${AI_GATEWAY_PG_PASSWORD}@localhost:${postgres_port}/${AI_GATEWAY_DATABASE_NAME}?sslmode=disable" fi echo "[ai-gateway] using configured local database connection (credentials redacted)" if [[ "${AI_GATEWAY_SKIP_DB_CREATE:-}" == "1" ]]; then echo "[ai-gateway] skipping Docker database creation" elif [[ -n "$postgres_container" && ( "$database_url_was_configured" == "0" || "$pg_container_was_configured" == "1" ) ]]; then scripts/create-database.sh else echo "[ai-gateway] no matching Docker database container selected; skipping database creation" fi pnpm nx run api:migrate stop_stale_api_processes exec pnpm nx run-many -t dev -p api web --parallel=2