-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev.sh
More file actions
executable file
·186 lines (158 loc) · 5.14 KB
/
Copy pathdev.sh
File metadata and controls
executable file
·186 lines (158 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_DIR="$ROOT_DIR/webapp/database-explorer-lite"
FRONTEND_DIR="$APP_DIR/frontend"
BACKEND_DIR="$APP_DIR/backend"
FRONTEND_HOST="${FRONTEND_HOST:-127.0.0.1}"
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
BACKEND_HOST="${BACKEND_HOST:-127.0.0.1}"
BACKEND_PORT="${BACKEND_PORT:-8000}"
BACKEND_PYTHON="${BACKEND_PYTHON:-python3}"
PARENT_DIR="$(cd "$ROOT_DIR/.." && pwd)"
# Default flow: backend only (serves frontend/dist when present).
# Set FRONTEND_DEV=1 to also run Vite dev server.
FRONTEND_DEV="${FRONTEND_DEV:-0}"
BACKEND_RELOAD="${BACKEND_RELOAD:-0}"
FRONTEND_PID=""
BACKEND_PID=""
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "Missing required command: $1" >&2
exit 1
fi
}
ensure_frontend_dist() {
local dist_dir="$FRONTEND_DIR/dist"
local index_file="$dist_dir/index.html"
if [[ ! -f "$index_file" ]]; then
echo "[dev] Missing frontend build at $index_file"
else
local js_rel css_rel
js_rel="$(grep -oE 'src="/assets/[^"]+\\.js"' "$index_file" | head -n1 | cut -d'"' -f2 || true)"
css_rel="$(grep -oE 'href="/assets/[^"]+\\.css"' "$index_file" | head -n1 | cut -d'"' -f2 || true)"
if [[ -n "$js_rel" && -n "$css_rel" && -f "$dist_dir${js_rel#/}" && -f "$dist_dir${css_rel#/}" ]]; then
return
fi
echo "[dev] Frontend build exists but referenced assets are missing; rebuilding."
fi
require_cmd npm
if [[ ! -d "$FRONTEND_DIR/node_modules" ]]; then
echo "[dev] Installing frontend dependencies"
(
cd "$FRONTEND_DIR"
npm install
)
fi
echo "[dev] Building frontend"
(
cd "$FRONTEND_DIR"
npm run build
)
}
load_first_env() {
local env_candidates=(
"$ROOT_DIR/.env"
"$APP_DIR/.env"
"$BACKEND_DIR/.env"
)
for env_path in "${env_candidates[@]}"; do
if [[ -f "$env_path" ]]; then
echo "[dev] Loading environment from $env_path"
set -a
# shellcheck source=/dev/null
. "$env_path"
set +a
return
fi
done
}
cleanup() {
local exit_code=$?
set +e
if [[ -n "$FRONTEND_PID" ]] && kill -0 "$FRONTEND_PID" >/dev/null 2>&1; then
kill "$FRONTEND_PID" >/dev/null 2>&1
wait "$FRONTEND_PID" >/dev/null 2>&1
fi
if [[ -n "$BACKEND_PID" ]] && kill -0 "$BACKEND_PID" >/dev/null 2>&1; then
kill "$BACKEND_PID" >/dev/null 2>&1
wait "$BACKEND_PID" >/dev/null 2>&1
fi
exit "$exit_code"
}
trap cleanup EXIT INT TERM
load_first_env
# Prefer active/project virtualenv interpreter if caller did not override BACKEND_PYTHON.
if [[ "${BACKEND_PYTHON:-python3}" == "python3" ]]; then
if [[ -n "${VIRTUAL_ENV:-}" && -x "${VIRTUAL_ENV}/bin/python" ]]; then
BACKEND_PYTHON="${VIRTUAL_ENV}/bin/python"
elif [[ -n "${CONDA_PREFIX:-}" && -x "${CONDA_PREFIX}/bin/python" ]]; then
BACKEND_PYTHON="${CONDA_PREFIX}/bin/python"
elif [[ -x "$BACKEND_DIR/.venv/bin/python" ]]; then
BACKEND_PYTHON="$BACKEND_DIR/.venv/bin/python"
elif [[ -x "$BACKEND_DIR/venv/bin/python" ]]; then
BACKEND_PYTHON="$BACKEND_DIR/venv/bin/python"
elif [[ -x "$ROOT_DIR/.venv/bin/python" ]]; then
BACKEND_PYTHON="$ROOT_DIR/.venv/bin/python"
elif [[ -x "$ROOT_DIR/venv/bin/python" ]]; then
BACKEND_PYTHON="$ROOT_DIR/venv/bin/python"
elif [[ -x "$PARENT_DIR/.venv/bin/python" ]]; then
BACKEND_PYTHON="$PARENT_DIR/.venv/bin/python"
elif [[ -x "$PARENT_DIR/venv/bin/python" ]]; then
BACKEND_PYTHON="$PARENT_DIR/venv/bin/python"
elif command -v python >/dev/null 2>&1; then
BACKEND_PYTHON="python"
fi
fi
require_cmd "$BACKEND_PYTHON"
if ! "$BACKEND_PYTHON" -c "import uvicorn" >/dev/null 2>&1; then
echo "[dev] Missing Python module: uvicorn in interpreter: $BACKEND_PYTHON" >&2
echo "[dev] Install backend dependencies with:" >&2
echo " $BACKEND_PYTHON -m pip install -r \"$BACKEND_DIR/requirements.txt\"" >&2
exit 1
fi
if [[ "$FRONTEND_DEV" == "1" ]]; then
require_cmd npm
if [[ ! -d "$FRONTEND_DIR/node_modules" ]]; then
echo "[dev] Installing frontend dependencies"
(
cd "$FRONTEND_DIR"
npm install
)
fi
else
ensure_frontend_dist
fi
backend_args=(main:app --host "$BACKEND_HOST" --port "$BACKEND_PORT")
if [[ "$BACKEND_RELOAD" == "1" ]]; then
backend_args+=(--reload)
fi
echo "[dev] Starting backend on http://$BACKEND_HOST:$BACKEND_PORT"
(
cd "$BACKEND_DIR"
exec "$BACKEND_PYTHON" -m uvicorn "${backend_args[@]}"
) &
BACKEND_PID=$!
if [[ "$FRONTEND_DEV" == "1" ]]; then
echo "[dev] Starting frontend on http://$FRONTEND_HOST:$FRONTEND_PORT"
(
cd "$FRONTEND_DIR"
exec npm run dev -- --host "$FRONTEND_HOST" --port "$FRONTEND_PORT"
) &
FRONTEND_PID=$!
echo
echo "Frontend (Vite): http://$FRONTEND_HOST:$FRONTEND_PORT"
echo "Backend API: http://$BACKEND_HOST:$BACKEND_PORT"
echo "Press Ctrl+C to stop both servers."
echo
wait -n "$BACKEND_PID" "$FRONTEND_PID"
else
echo
echo "Web UI: http://$BACKEND_HOST:$BACKEND_PORT"
echo "API: http://$BACKEND_HOST:$BACKEND_PORT"
echo "Note: this mode serves frontend from frontend/dist via FastAPI."
echo "Set FRONTEND_DEV=1 for Vite hot reload."
echo "Press Ctrl+C to stop."
echo
wait "$BACKEND_PID"
fi