#!/usr/bin/env bash # Start the API (port 3000) and Flutter web dev server (port 8080) with merged logs. # Usage: ./startup.sh set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" API_PORT=3000 WEB_PORT=8080 if [ -f "$ROOT/scripts/flutter-env.sh" ]; then # shellcheck source=/dev/null source "$ROOT/scripts/flutter-env.sh" fi log() { printf '%s\n' "$*"; } kill_port() { local port=$1 if command -v fuser >/dev/null 2>&1; then if fuser "${port}/tcp" >/dev/null 2>&1; then log "Stopping process(es) on port ${port}..." fuser -k "${port}/tcp" >/dev/null 2>&1 || true sleep 0.5 fi return fi if ! command -v lsof >/dev/null 2>&1; then warn "Cannot free port ${port}: install fuser or lsof" return fi local pids pids="$(lsof -t -iTCP:"${port}" -sTCP:LISTEN 2>/dev/null || true)" if [ -n "$pids" ]; then log "Stopping process(es) on port ${port}: ${pids}" # shellcheck disable=SC2086 kill ${pids} 2>/dev/null || true sleep 0.5 # shellcheck disable=SC2086 kill -9 ${pids} 2>/dev/null || true fi } warn() { printf 'WARN: %s\n' "$*" >&2; } prefix_lines() { local tag=$1 while IFS= read -r line || [ -n "${line:-}" ]; do printf '[%s] %s\n' "$tag" "$line" done } cleanup() { trap - INT TERM EXIT log "Shutting down..." if [ -n "${API_PID:-}" ]; then kill "$API_PID" 2>/dev/null || true; fi if [ -n "${WEB_PID:-}" ]; then kill "$WEB_PID" 2>/dev/null || true; fi kill_port "$API_PORT" kill_port "$WEB_PORT" wait 2>/dev/null || true } trap cleanup INT TERM EXIT log "Freeing ports ${API_PORT} (API) and ${WEB_PORT} (web)..." kill_port "$API_PORT" kill_port "$WEB_PORT" if [ ! -f "$ROOT/server/.env" ]; then warn "Missing server/.env — copy server/.env.example and configure it first." fi log "Starting API on http://localhost:${API_PORT} ..." ( cd "$ROOT/server" dart run bin/server.dart 2>&1 | prefix_lines api ) & API_PID=$! log "Starting web app on http://localhost:${WEB_PORT} ..." ( cd "$ROOT" flutter run -d web-server \ --dart-define=API_BASE_URL="http://localhost:${API_PORT}" \ 2>&1 | prefix_lines web ) & WEB_PID=$! log "Both services running. Press Ctrl+C to stop." log " API: http://localhost:${API_PORT}" log " Web: http://localhost:${WEB_PORT}" log "" wait -n 2>/dev/null || wait || true exit_code=$? cleanup exit "$exit_code"