chore(dev): harden start-dev shutdown and DATABASE_URL setup.

Load root .env for Prisma, stop dev servers via process groups, and sync server lockfile metadata after install.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-12 10:51:26 +02:00
co-authored by Cursor
parent 465c58ee69
commit 8b51d920da
2 changed files with 93 additions and 14 deletions
+92 -14
View File
@@ -38,6 +38,32 @@ resolve_node_toolchain() {
command -v npm >/dev/null 2>&1 command -v npm >/dev/null 2>&1
} }
load_root_env() {
local env_file="$REPO_ROOT/.env"
if [ ! -f "$env_file" ]; then
return 0
fi
set -a
# shellcheck disable=SC1090
. "$env_file"
set +a
}
resolve_database_url() {
if [ -n "${DATABASE_URL:-}" ]; then
printf '%s' "$DATABASE_URL"
return 0
fi
local user="${POSTGRES_USER:-postgres}"
local password="${POSTGRES_PASSWORD:-}"
local db="${POSTGRES_DB:-daagbox}"
[ -z "$user" ] && user=postgres
[ -z "$password" ] && password=postgres
[ -z "$db" ] && db=daagbox
printf 'postgresql://%s:%s@localhost:5432/%s?schema=public' "$user" "$password" "$db"
}
check_dev_env() { check_dev_env() {
local env_file="$REPO_ROOT/.env" local env_file="$REPO_ROOT/.env"
if [ ! -f "$env_file" ]; then if [ ! -f "$env_file" ]; then
@@ -91,38 +117,84 @@ echo "========================================"
echo "Preparing to (re)start services..." echo "Preparing to (re)start services..."
require_node_toolchain require_node_toolchain
load_root_env
export DATABASE_URL="$(resolve_database_url)"
check_dev_env check_dev_env
# Clean up processes running on ports # Clean up processes running on ports
stop_process_tree() {
local pid=$1
[ -z "$pid" ] && return 0
if ! kill -0 "$pid" 2>/dev/null; then
return 0
fi
local child
for child in $(pgrep -P "$pid" 2>/dev/null || true); do
stop_process_tree "$child"
done
kill -TERM "$pid" 2>/dev/null || true
}
stop_process_group() {
local pgid=$1
[ -z "$pgid" ] && return 0
kill -TERM "-$pgid" 2>/dev/null || true
}
force_stop_process_group() {
local pgid=$1
[ -z "$pgid" ] && return 0
kill -KILL "-$pgid" 2>/dev/null || true
}
cleanup_port() { cleanup_port() {
local port=$1 local port=$1
if command -v lsof >/dev/null 2>&1; then if command -v lsof >/dev/null 2>&1; then
local pid=$(lsof -t -i:$port) local pids
if [ ! -z "$pid" ]; then pids=$(lsof -t -i:"$port" 2>/dev/null || true)
echo "Port $port is currently in use by PID $pid. Stopping process..." if [ -n "$pids" ]; then
kill -9 $pid 2>/dev/null echo "Port $port is currently in use. Stopping process(es)..."
local pid
for pid in $pids; do
stop_process_tree "$pid"
done
sleep 0.3
for pid in $pids; do
kill -KILL "$pid" 2>/dev/null || true
done
fi fi
elif command -v fuser >/dev/null 2>&1; then elif command -v fuser >/dev/null 2>&1; then
echo "Port $port is currently in use. Stopping process..." echo "Port $port is currently in use. Stopping process..."
fuser -k $port/tcp 2>/dev/null fuser -k "$port"/tcp 2>/dev/null
fi fi
} }
cleanup_port $SERVER_PORT BACKEND_PGID=""
cleanup_port $CLIENT_PORT CLIENT_PGID=""
# Clean exit handler
cleanup_all() { cleanup_all() {
echo "" echo ""
echo "Stopping all dev servers..." echo "Stopping all dev servers..."
# Kill all child jobs
kill $(jobs -p) 2>/dev/null stop_process_group "$BACKEND_PGID"
stop_process_group "$CLIENT_PGID"
sleep 0.5
force_stop_process_group "$BACKEND_PGID"
force_stop_process_group "$CLIENT_PGID"
cleanup_port "$SERVER_PORT"
cleanup_port "$CLIENT_PORT"
exit 0 exit 0
} }
# Trap termination signals # Trap termination signals
trap cleanup_all SIGINT SIGTERM EXIT trap cleanup_all SIGINT SIGTERM EXIT
cleanup_port "$SERVER_PORT"
cleanup_port "$CLIENT_PORT"
# Manage PostgreSQL Docker container # Manage PostgreSQL Docker container
if command -v docker >/dev/null 2>&1; then if command -v docker >/dev/null 2>&1; then
echo "Checking PostgreSQL Docker container (postgres-daagbox)..." echo "Checking PostgreSQL Docker container (postgres-daagbox)..."
@@ -189,8 +261,9 @@ if [ ! -d node_modules ]; then
echo "Error: server/node_modules missing. Run: cd server && npm ci" echo "Error: server/node_modules missing. Run: cd server && npm ci"
exit 1 exit 1
fi fi
npm run dev & setsid npm run dev &
BACKEND_PID=$! BACKEND_PID=$!
BACKEND_PGID=$BACKEND_PID
cd "$REPO_ROOT" || exit 1 cd "$REPO_ROOT" || exit 1
# Sleep briefly to let server start up # Sleep briefly to let server start up
@@ -205,7 +278,9 @@ echo "Starting frontend dev server..."
cd "$REPO_ROOT/client" || exit 1 cd "$REPO_ROOT/client" || exit 1
if [ ! -d node_modules ]; then if [ ! -d node_modules ]; then
echo "Error: client/node_modules missing. Run: cd client && npm ci" echo "Error: client/node_modules missing. Run: cd client && npm ci"
kill "$BACKEND_PID" 2>/dev/null stop_process_group "$BACKEND_PGID"
sleep 0.3
force_stop_process_group "$BACKEND_PGID"
exit 1 exit 1
fi fi
# Vite 6+ via plugin-react 4; refresh lockfile after package.json changes # Vite 6+ via plugin-react 4; refresh lockfile after package.json changes
@@ -213,14 +288,17 @@ if ! node -e "require.resolve('vite/package.json')" 2>/dev/null; then
echo "Client dependencies incomplete — running npm ci..." echo "Client dependencies incomplete — running npm ci..."
npm ci || exit 1 npm ci || exit 1
fi fi
npm run dev & setsid npm run dev &
CLIENT_PID=$! CLIENT_PID=$!
CLIENT_PGID=$CLIENT_PID
cd "$REPO_ROOT" || exit 1 cd "$REPO_ROOT" || exit 1
sleep 1.5 sleep 1.5
if ! kill -0 "$CLIENT_PID" 2>/dev/null; then if ! kill -0 "$CLIENT_PID" 2>/dev/null; then
echo "Error: Frontend dev server exited immediately. Check client logs above." echo "Error: Frontend dev server exited immediately. Check client logs above."
kill "$BACKEND_PID" 2>/dev/null stop_process_group "$BACKEND_PGID"
sleep 0.3
force_stop_process_group "$BACKEND_PGID"
exit 1 exit 1
fi fi
+1
View File
@@ -7,6 +7,7 @@
"": { "": {
"name": "server", "name": "server",
"version": "1.0.0", "version": "1.0.0",
"hasInstallScript": true,
"dependencies": { "dependencies": {
"@prisma/client": "^5.10.2", "@prisma/client": "^5.10.2",
"@simplewebauthn/server": "^9.0.3", "@simplewebauthn/server": "^9.0.3",