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:
+92
-14
@@ -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
|
||||||
|
|
||||||
|
|||||||
Generated
+1
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user