Skip to content

Commit c577989

Browse files
committed
chore: add local project startup script
1 parent 5803c68 commit c577989

1 file changed

Lines changed: 157 additions & 0 deletions

File tree

startProject

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
RUNTIME_DIR="$ROOT_DIR/.runtime"
6+
COMPOSE_FILE="$ROOT_DIR/infra/compose/compose.yaml"
7+
8+
API_PORT="${API_PORT:-18080}"
9+
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
10+
KEYCLOAK_HEALTH_URL="${KEYCLOAK_HEALTH_URL:-http://localhost:19000/health/ready}"
11+
BACKEND_HEALTH_URL="${BACKEND_HEALTH_URL:-http://localhost:${API_PORT}/actuator/health}"
12+
FRONTEND_URL="${FRONTEND_URL:-http://localhost:${FRONTEND_PORT}/}"
13+
14+
mkdir -p "$RUNTIME_DIR"
15+
16+
info() {
17+
printf '[startProject] %s\n' "$*"
18+
}
19+
20+
fail() {
21+
printf '[startProject] ERROR: %s\n' "$*" >&2
22+
exit 1
23+
}
24+
25+
command_exists() {
26+
command -v "$1" >/dev/null 2>&1
27+
}
28+
29+
http_ok() {
30+
curl -fsS "$1" >/dev/null 2>&1
31+
}
32+
33+
port_open() {
34+
local port="$1"
35+
36+
if command_exists nc; then
37+
nc -z localhost "$port" >/dev/null 2>&1
38+
return
39+
fi
40+
41+
curl -fsS "http://localhost:${port}/" >/dev/null 2>&1
42+
}
43+
44+
wait_for_url() {
45+
local label="$1"
46+
local url="$2"
47+
local attempts="${3:-60}"
48+
local delay_seconds="${4:-2}"
49+
50+
info "Waiting for ${label}..."
51+
for _ in $(seq 1 "$attempts"); do
52+
if http_ok "$url"; then
53+
info "${label} is ready."
54+
return 0
55+
fi
56+
sleep "$delay_seconds"
57+
done
58+
59+
return 1
60+
}
61+
62+
start_background() {
63+
local name="$1"
64+
local pid_file="$2"
65+
local log_file="$3"
66+
shift 3
67+
68+
if [[ -f "$pid_file" ]]; then
69+
local existing_pid
70+
existing_pid="$(cat "$pid_file")"
71+
if [[ -n "$existing_pid" ]] && kill -0 "$existing_pid" >/dev/null 2>&1; then
72+
info "${name} is already running with PID ${existing_pid}."
73+
return 0
74+
fi
75+
fi
76+
77+
info "Starting ${name}. Logs: ${log_file}"
78+
(
79+
cd "$ROOT_DIR"
80+
"$@"
81+
) >"$log_file" 2>&1 &
82+
83+
echo "$!" >"$pid_file"
84+
info "${name} PID: $(cat "$pid_file")"
85+
}
86+
87+
ensure_requirements() {
88+
command_exists docker || fail "Docker is not installed or not on PATH."
89+
docker compose version >/dev/null 2>&1 || fail "Docker Compose is not available."
90+
command_exists curl || fail "curl is required for readiness checks."
91+
[[ -x "$ROOT_DIR/backend/mvnw" ]] || fail "backend/mvnw is missing or not executable."
92+
command_exists npm || fail "npm is not installed or not on PATH."
93+
}
94+
95+
start_infra() {
96+
info "Starting local infrastructure with Docker Compose."
97+
docker compose -f "$COMPOSE_FILE" up -d
98+
wait_for_url "Keycloak" "$KEYCLOAK_HEALTH_URL" 90 2 || fail "Keycloak did not become healthy. Check Docker logs."
99+
}
100+
101+
start_backend() {
102+
if http_ok "$BACKEND_HEALTH_URL"; then
103+
info "Backend is already healthy at ${BACKEND_HEALTH_URL}."
104+
return 0
105+
fi
106+
107+
if port_open "$API_PORT"; then
108+
info "Port ${API_PORT} is already in use; assuming the backend is starting or running."
109+
else
110+
start_background \
111+
"backend API" \
112+
"$RUNTIME_DIR/backend.pid" \
113+
"$RUNTIME_DIR/backend.log" \
114+
"$ROOT_DIR/backend/mvnw" -f "$ROOT_DIR/backend/pom.xml" spring-boot:run
115+
fi
116+
117+
wait_for_url "backend API" "$BACKEND_HEALTH_URL" 90 2 || fail "Backend did not become healthy. Check $RUNTIME_DIR/backend.log."
118+
}
119+
120+
start_frontend() {
121+
if http_ok "$FRONTEND_URL"; then
122+
info "Frontend is already serving at ${FRONTEND_URL}."
123+
return 0
124+
fi
125+
126+
if [[ ! -d "$ROOT_DIR/frontend/node_modules" ]]; then
127+
info "Installing frontend dependencies."
128+
(cd "$ROOT_DIR/frontend" && npm ci)
129+
fi
130+
131+
if port_open "$FRONTEND_PORT"; then
132+
info "Port ${FRONTEND_PORT} is already in use; assuming the frontend is starting or running."
133+
else
134+
start_background \
135+
"frontend" \
136+
"$RUNTIME_DIR/frontend.pid" \
137+
"$RUNTIME_DIR/frontend.log" \
138+
npm --prefix "$ROOT_DIR/frontend" run dev
139+
fi
140+
141+
wait_for_url "frontend" "$FRONTEND_URL" 60 2 || fail "Frontend did not become ready. Check $RUNTIME_DIR/frontend.log."
142+
}
143+
144+
main() {
145+
ensure_requirements
146+
start_infra
147+
start_backend
148+
start_frontend
149+
150+
info "PayLedger is running."
151+
info "Frontend: ${FRONTEND_URL}"
152+
info "Backend health: ${BACKEND_HEALTH_URL}"
153+
info "Keycloak: http://localhost:18081/"
154+
info "Logs: ${RUNTIME_DIR}"
155+
}
156+
157+
main "$@"

0 commit comments

Comments
 (0)