Files
LMS/start-dev.sh
T

153 lines
6.0 KiB
Bash
Executable File

#!/bin/bash
# ─────────────────────────────────────────────────────────────────────────────
# start-dev.sh — Start LMS in local development mode
# Runs Backend (uvicorn) + Frontend (next dev) in parallel
# Usage:
# ./start-dev.sh # start both
# ./start-dev.sh backend # start backend only
# ./start-dev.sh frontend # start frontend only
# ─────────────────────────────────────────────────────────────────────────────
set -e
cd "$(dirname "$0")"
# ── Load .env ─────────────────────────────────────────────────────────────────
if [ ! -f .env ]; then
echo "❌ .env not found. Copy .env.example → .env and fill in values."
exit 1
fi
# Export only the variables we need (skip GHCR secrets)
export $(grep -v '^#' .env | grep -E 'POSTGRES_(DB|USER|PASSWORD)|JWT_SECRET_KEY|ACCESS_TOKEN_EXPIRE_MINUTES|FRONTEND_PORT' | xargs)
# Defaults
POSTGRES_DB="${POSTGRES_DB:-lms_db}"
POSTGRES_USER="${POSTGRES_USER:-lms_user}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-lms_test_password_123}"
JWT_SECRET_KEY="${JWT_SECRET_KEY:?JWT_SECRET_KEY is not set in .env}"
FRONTEND_PORT="${FRONTEND_PORT:-3011}"
BACKEND_PORT="${BACKEND_PORT:-8001}"
DATABASE_URL="postgresql+psycopg2://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}"
UPLOAD_DIR="./backend/uploads"
# ── Colors ────────────────────────────────────────────────────────────────────
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
TARGET="${1:-both}"
# ─────────────────────────────────────────────────────────────────────────────
start_backend() {
echo -e "${CYAN}${BOLD}▶ Starting Backend${NC} (port ${BACKEND_PORT})"
# Kill any process already occupying the backend port
local old_pid
old_pid=$(lsof -ti tcp:"$BACKEND_PORT" 2>/dev/null || true)
if [ -n "$old_pid" ]; then
echo -e "${YELLOW} Killing process on port ${BACKEND_PORT} (PID ${old_pid})...${NC}"
kill -9 $old_pid 2>/dev/null || true
sleep 0.5
fi
# Check Python venv
VENV=""
if [ -d backend/.venv ]; then
VENV="backend/.venv/bin/"
elif [ -d backend/venv ]; then
VENV="backend/venv/bin/"
fi
# Run Alembic migrations first
echo -e "${YELLOW} Running Alembic migrations...${NC}"
(
cd backend
DATABASE_URL="$DATABASE_URL" \
${VENV}alembic upgrade head 2>&1 | sed 's/^/ [alembic] /'
)
mkdir -p "$UPLOAD_DIR"
echo -e "${GREEN} Backend ready → http://localhost:${BACKEND_PORT}${NC}"
echo -e "${GREEN} API docs → http://localhost:${BACKEND_PORT}/docs${NC}"
echo ""
DATABASE_URL="$DATABASE_URL" \
JWT_SECRET_KEY="$JWT_SECRET_KEY" \
ACCESS_TOKEN_EXPIRE_MINUTES="$ACCESS_TOKEN_EXPIRE_MINUTES" \
UPLOAD_DIR="$UPLOAD_DIR" \
REDIS_URL="${REDIS_URL:-redis://localhost:6379/0}" \
${VENV}uvicorn main:app \
--host 0.0.0.0 \
--port "$BACKEND_PORT" \
--reload \
--app-dir backend
}
# ─────────────────────────────────────────────────────────────────────────────
start_frontend() {
echo -e "${CYAN}${BOLD}▶ Starting Frontend${NC} (port ${FRONTEND_PORT})"
# Kill any process already occupying the frontend port
local old_pid
old_pid=$(lsof -ti tcp:"$FRONTEND_PORT" 2>/dev/null || true)
if [ -n "$old_pid" ]; then
echo -e "${YELLOW} Killing process on port ${FRONTEND_PORT} (PID ${old_pid})...${NC}"
kill -9 $old_pid 2>/dev/null || true
sleep 0.5
fi
if [ ! -d frontend/node_modules ]; then
echo -e "${YELLOW} node_modules not found — running npm install...${NC}"
(cd frontend && npm install)
fi
echo -e "${GREEN} Frontend ready → http://localhost:${FRONTEND_PORT}${NC}"
echo ""
NEXT_PUBLIC_API_URL="http://localhost:${BACKEND_PORT}" \
PORT="$FRONTEND_PORT" \
npm --prefix frontend run dev
}
# ─────────────────────────────────────────────────────────────────────────────
# Entrypoint
# ─────────────────────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}╔══════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ LMS — Dev Server ║${NC}"
echo -e "${BOLD}╚══════════════════════════════════════╝${NC}"
echo ""
case "$TARGET" in
backend)
start_backend
;;
frontend)
start_frontend
;;
both)
# Run backend in background, frontend in foreground
# Trap Ctrl+C to kill both
trap 'echo -e "\n${RED}Stopping...${NC}"; kill 0' INT TERM
start_backend &
BACKEND_PID=$!
# Small delay so backend logs don't jumble with frontend boot
sleep 2
start_frontend &
FRONTEND_PID=$!
echo ""
echo -e "${BOLD}Running. Press Ctrl+C to stop both servers.${NC}"
echo ""
wait $BACKEND_PID $FRONTEND_PID
;;
*)
echo "Usage: $0 [both|backend|frontend]"
exit 1
;;
esac