0276d8445e
Vite 8 benötigt native @rolldown-Bindings, die npm oft nicht installiert. Downgrade auf Vite 6 mit plugin-react 4 behebt den Dev-Server-Absturz; start-dev.sh prüft client/node_modules vor dem Start. Co-authored-by: Cursor <cursoragent@cursor.com>
216 lines
6.3 KiB
Bash
Executable File
216 lines
6.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Configuration
|
|
SERVER_PORT=5000
|
|
CLIENT_PORT=5173
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
resolve_node_toolchain() {
|
|
# Common install locations when login shell PATH is not loaded
|
|
if command -v npm >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
|
|
if [ -s "$HOME/.nvm/nvm.sh" ]; then
|
|
# shellcheck disable=SC1090
|
|
. "$HOME/.nvm/nvm.sh"
|
|
elif [ -s "/usr/local/nvm/nvm.sh" ]; then
|
|
# shellcheck disable=SC1090
|
|
. "/usr/local/nvm/nvm.sh"
|
|
fi
|
|
|
|
if [ -d "$HOME/.fnm" ] && command -v fnm >/dev/null 2>&1; then
|
|
eval "$(fnm env)"
|
|
fi
|
|
|
|
for candidate in \
|
|
/usr/local/bin/npm \
|
|
/usr/bin/npm \
|
|
"$HOME/.local/share/fnm/current/bin/npm" \
|
|
"$HOME/.nvm/versions/node/"*/bin/npm; do
|
|
if [ -x "$candidate" ]; then
|
|
export PATH="$(dirname "$candidate"):$PATH"
|
|
break
|
|
fi
|
|
done
|
|
|
|
command -v npm >/dev/null 2>&1
|
|
}
|
|
|
|
check_dev_env() {
|
|
local env_file="$REPO_ROOT/.env"
|
|
if [ ! -f "$env_file" ]; then
|
|
echo "Warning: $env_file missing — copy from .env.example (RP_ID, ORIGIN, SESSION_SECRET)."
|
|
return
|
|
fi
|
|
|
|
local origin_line origin_val
|
|
origin_line=$(grep -E '^ORIGIN=' "$env_file" | tail -1 || true)
|
|
origin_val="${origin_line#ORIGIN=}"
|
|
origin_val="${origin_val%\"}"
|
|
origin_val="${origin_val#\"}"
|
|
local expected_origin="http://localhost:$CLIENT_PORT"
|
|
if [ -n "$origin_val" ] && [ "$origin_val" != "$expected_origin" ]; then
|
|
echo "Warning: ORIGIN=$origin_val — for Vite dev use ORIGIN=$expected_origin (session cookie + CORS)."
|
|
fi
|
|
|
|
local secret_line secret_val
|
|
secret_line=$(grep -E '^SESSION_SECRET=' "$env_file" | tail -1 || true)
|
|
secret_val="${secret_line#SESSION_SECRET=}"
|
|
secret_val="${secret_val%\"}"
|
|
secret_val="${secret_val#\"}"
|
|
if [ -z "$secret_val" ]; then
|
|
echo "Note: SESSION_SECRET is empty — backend uses a dev-only fallback (not for production)."
|
|
elif [ "${#secret_val}" -lt 32 ]; then
|
|
echo "Warning: SESSION_SECRET should be at least 32 characters."
|
|
fi
|
|
}
|
|
|
|
require_node_toolchain() {
|
|
if resolve_node_toolchain; then
|
|
echo "Using Node $(node -v), npm $(npm -v)"
|
|
return 0
|
|
fi
|
|
|
|
echo "Error: npm was not found in PATH."
|
|
echo ""
|
|
echo "This script starts local Vite/Express dev servers and requires Node.js 20+ with npm."
|
|
echo "Install Node.js on this machine, or use the Docker-based stack instead:"
|
|
echo " ./scripts/start-dev-docker.sh"
|
|
echo ""
|
|
echo "On the production host, prefer updating the running stack:"
|
|
echo " docker compose -f docker-compose.yml up -d --build"
|
|
echo " # or from your workstation: ./scripts/update-prod.sh"
|
|
exit 1
|
|
}
|
|
|
|
echo "========================================"
|
|
echo " Kapteins Daagbok Dev Environment "
|
|
echo "========================================"
|
|
echo "Preparing to (re)start services..."
|
|
|
|
require_node_toolchain
|
|
check_dev_env
|
|
|
|
# Clean up processes running on ports
|
|
cleanup_port() {
|
|
local port=$1
|
|
if command -v lsof >/dev/null 2>&1; then
|
|
local pid=$(lsof -t -i:$port)
|
|
if [ ! -z "$pid" ]; then
|
|
echo "Port $port is currently in use by PID $pid. Stopping process..."
|
|
kill -9 $pid 2>/dev/null
|
|
fi
|
|
elif command -v fuser >/dev/null 2>&1; then
|
|
echo "Port $port is currently in use. Stopping process..."
|
|
fuser -k $port/tcp 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
cleanup_port $SERVER_PORT
|
|
cleanup_port $CLIENT_PORT
|
|
|
|
# Clean exit handler
|
|
cleanup_all() {
|
|
echo ""
|
|
echo "Stopping all dev servers..."
|
|
# Kill all child jobs
|
|
kill $(jobs -p) 2>/dev/null
|
|
exit 0
|
|
}
|
|
|
|
# Trap termination signals
|
|
trap cleanup_all SIGINT SIGTERM EXIT
|
|
|
|
# Manage PostgreSQL Docker container
|
|
if command -v docker >/dev/null 2>&1; then
|
|
echo "Checking PostgreSQL Docker container (postgres-daagbox)..."
|
|
if docker ps -a --format '{{.Names}}' | grep -Eq "^postgres-daagbox$"; then
|
|
echo "Found existing postgres-daagbox container. Restarting..."
|
|
docker restart postgres-daagbox >/dev/null
|
|
else
|
|
echo "postgres-daagbox container not found. Creating and starting a new one..."
|
|
docker run -d \
|
|
--name postgres-daagbox \
|
|
-p 5432:5432 \
|
|
-e POSTGRES_USER=postgres \
|
|
-e POSTGRES_PASSWORD=postgres \
|
|
-e POSTGRES_DB=daagbox \
|
|
postgres:16 >/dev/null
|
|
fi
|
|
|
|
# Wait for PostgreSQL to be ready
|
|
echo "Waiting for PostgreSQL database to be ready..."
|
|
TIMEOUT=15
|
|
COUNTER=0
|
|
until docker exec postgres-daagbox pg_isready -U postgres >/dev/null 2>&1; do
|
|
sleep 0.5
|
|
COUNTER=$((COUNTER + 1))
|
|
if [ $COUNTER -ge 30 ]; then
|
|
echo "Warning: PostgreSQL did not start within $TIMEOUT seconds. Proceeding anyway..."
|
|
break
|
|
fi
|
|
done
|
|
if [ $COUNTER -lt 30 ]; then
|
|
echo "PostgreSQL is ready!"
|
|
fi
|
|
else
|
|
echo "Warning: Docker command not found. Skipping PostgreSQL container management."
|
|
fi
|
|
|
|
# Start backend server
|
|
echo "Starting backend API server..."
|
|
cd "$REPO_ROOT/server" || exit 1
|
|
if [ ! -d node_modules ]; then
|
|
echo "Error: server/node_modules missing. Run: cd server && npm ci"
|
|
exit 1
|
|
fi
|
|
npm run dev &
|
|
BACKEND_PID=$!
|
|
cd "$REPO_ROOT" || exit 1
|
|
|
|
# Sleep briefly to let server start up
|
|
sleep 1.5
|
|
if ! kill -0 "$BACKEND_PID" 2>/dev/null; then
|
|
echo "Error: Backend dev server exited immediately. Check server logs above."
|
|
exit 1
|
|
fi
|
|
|
|
# Start frontend client
|
|
echo "Starting frontend dev server..."
|
|
cd "$REPO_ROOT/client" || exit 1
|
|
if [ ! -d node_modules ]; then
|
|
echo "Error: client/node_modules missing. Run: cd client && npm ci"
|
|
kill "$BACKEND_PID" 2>/dev/null
|
|
exit 1
|
|
fi
|
|
# Vite 6+ via plugin-react 4; refresh lockfile after package.json changes
|
|
if ! node -e "require.resolve('vite/package.json')" 2>/dev/null; then
|
|
echo "Client dependencies incomplete — running npm ci..."
|
|
npm ci || exit 1
|
|
fi
|
|
npm run dev &
|
|
CLIENT_PID=$!
|
|
cd "$REPO_ROOT" || exit 1
|
|
|
|
sleep 1.5
|
|
if ! kill -0 "$CLIENT_PID" 2>/dev/null; then
|
|
echo "Error: Frontend dev server exited immediately. Check client logs above."
|
|
kill "$BACKEND_PID" 2>/dev/null
|
|
exit 1
|
|
fi
|
|
|
|
echo "========================================"
|
|
echo "Dev services are now running:"
|
|
echo " -> Backend: http://localhost:$SERVER_PORT"
|
|
echo " -> Frontend: http://localhost:$CLIENT_PORT"
|
|
echo " -> API auth: HttpOnly session cookie (after Passkey login)"
|
|
echo " -> Health: http://localhost:$SERVER_PORT/api/health"
|
|
echo "========================================"
|
|
echo "Press Ctrl+C to terminate both servers."
|
|
echo "========================================"
|
|
|
|
# Block to keep parent process alive
|
|
wait
|