-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdev.sh
More file actions
executable file
·223 lines (186 loc) · 5.56 KB
/
dev.sh
File metadata and controls
executable file
·223 lines (186 loc) · 5.56 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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/env bash
set -euo pipefail
# Presenton local development runner (cloud-only)
# Starts:
# - FastAPI backend (127.0.0.1:8000)
# - Next.js frontend (127.0.0.1:3000)
# Optional:
# - MCP server (127.0.0.1:8001) with --with-mcp
#
# Usage:
# ./dev.sh
# ./dev.sh --setup
# ./dev.sh --with-mcp
# ./dev.sh --setup --with-mcp
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FASTAPI_DIR="$ROOT_DIR/servers/fastapi"
NEXTJS_DIR="$ROOT_DIR/servers/nextjs"
WITH_MCP="false"
DO_SETUP="false"
for arg in "$@"; do
case "$arg" in
--with-mcp) WITH_MCP="true" ;;
--setup) DO_SETUP="true" ;;
-h|--help)
sed -n '1,30p' "$0"
exit 0
;;
*)
echo "Unknown option: $arg"
echo "Use --help for usage."
exit 1
;;
esac
done
export APP_DATA_DIRECTORY="${APP_DATA_DIRECTORY:-$ROOT_DIR/app_data}"
export TEMP_DIRECTORY="${TEMP_DIRECTORY:-/tmp/presenton}"
export USER_CONFIG_PATH="${USER_CONFIG_PATH:-$APP_DATA_DIRECTORY/userConfig.json}"
export DATABASE_URL="${DATABASE_URL:-sqlite+aiosqlite:///$APP_DATA_DIRECTORY/fastapi.db}"
mkdir -p "$APP_DATA_DIRECTORY" "$TEMP_DIRECTORY"
if ! command -v npm >/dev/null 2>&1; then
echo "npm not found. Install Node.js + npm first."
exit 1
fi
if ! command -v python3 >/dev/null 2>&1; then
echo "python3 not found. Install Python 3.11 first."
exit 1
fi
if command -v python3.11 >/dev/null 2>&1; then
PYTHON_SETUP_CMD="python3.11"
else
PYTHON_SETUP_CMD="python3"
fi
if ! "$PYTHON_SETUP_CMD" -c 'import sys; raise SystemExit(0 if (sys.version_info.major, sys.version_info.minor)==(3,11) else 1)' >/dev/null 2>&1; then
echo "Python 3.11 is required. Found: $($PYTHON_SETUP_CMD -V 2>&1)"
echo "Install Python 3.11 and ensure 'python3.11' is available in PATH."
exit 1
fi
PYTHON_CMD="python3"
if [[ -x "$FASTAPI_DIR/.venv/bin/python" ]]; then
PYTHON_CMD="$FASTAPI_DIR/.venv/bin/python"
fi
setup_backend() {
local recreate_venv="false"
if [[ -x "$FASTAPI_DIR/.venv/bin/python" ]]; then
if ! "$FASTAPI_DIR/.venv/bin/python" -c 'import sys; raise SystemExit(0 if (sys.version_info.major, sys.version_info.minor)==(3,11) else 1)' >/dev/null 2>&1; then
recreate_venv="true"
echo "[setup] Existing backend virtualenv is not Python 3.11. Recreating..."
fi
fi
if [[ ! -x "$FASTAPI_DIR/.venv/bin/python" || "$recreate_venv" == "true" ]]; then
rm -rf "$FASTAPI_DIR/.venv"
echo "[setup] Creating backend virtualenv..."
"$PYTHON_SETUP_CMD" -m venv "$FASTAPI_DIR/.venv"
fi
echo "[setup] Installing backend dependencies..."
"$FASTAPI_DIR/.venv/bin/python" -m pip install -U pip >/dev/null
"$FASTAPI_DIR/.venv/bin/python" -m pip install -e "$FASTAPI_DIR"
PYTHON_CMD="$FASTAPI_DIR/.venv/bin/python"
}
setup_frontend() {
echo "[setup] Installing frontend dependencies..."
(cd "$NEXTJS_DIR" && npm ci)
}
if [[ "$DO_SETUP" == "true" ]]; then
setup_backend
setup_frontend
fi
if [[ -x "$FASTAPI_DIR/.venv/bin/python" ]]; then
PYTHON_CMD="$FASTAPI_DIR/.venv/bin/python"
if ! "$PYTHON_CMD" -c 'import sys; raise SystemExit(0 if (sys.version_info.major, sys.version_info.minor)==(3,11) else 1)' >/dev/null 2>&1; then
echo "Backend virtualenv uses incompatible Python: $($PYTHON_CMD -V 2>&1)"
echo "Run './dev.sh --setup' to recreate it with Python 3.11."
exit 1
fi
fi
if [[ ! -f "$NEXTJS_DIR/package.json" ]]; then
echo "Next.js package.json not found at $NEXTJS_DIR"
exit 1
fi
if [[ ! -f "$FASTAPI_DIR/server.py" ]]; then
echo "FastAPI server.py not found at $FASTAPI_DIR"
exit 1
fi
free_port_if_busy() {
local port="$1"
if ! command -v lsof >/dev/null 2>&1; then
return 0
fi
local pids
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
if [[ -z "$pids" ]]; then
return 0
fi
echo "[dev] Port $port is in use. Stopping existing process(es): $pids"
for pid in $pids; do
kill "$pid" 2>/dev/null || true
done
sleep 1
# Force kill if still running
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
if [[ -n "$pids" ]]; then
for pid in $pids; do
kill -9 "$pid" 2>/dev/null || true
done
fi
}
free_port_if_busy 8000
free_port_if_busy 3000
if [[ "$WITH_MCP" == "true" ]]; then
free_port_if_busy 8001
fi
echo "Starting Presenton local development"
echo "APP_DATA_DIRECTORY=$APP_DATA_DIRECTORY"
echo "TEMP_DIRECTORY=$TEMP_DIRECTORY"
echo "USER_CONFIG_PATH=$USER_CONFIG_PATH"
echo "DATABASE_URL=$DATABASE_URL"
echo "-> Starting FastAPI on http://127.0.0.1:8000"
(
cd "$FASTAPI_DIR"
exec "$PYTHON_CMD" server.py --port 8000 --reload true
) &
FASTAPI_PID=$!
MCP_PID=""
if [[ "$WITH_MCP" == "true" ]]; then
echo "-> Starting MCP server on http://127.0.0.1:8001"
(
cd "$FASTAPI_DIR"
exec "$PYTHON_CMD" mcp_server.py --port 8001
) &
MCP_PID=$!
fi
echo "-> Starting Next.js on http://127.0.0.1:3000"
(
cd "$NEXTJS_DIR"
exec npm run dev
) &
NEXTJS_PID=$!
cleanup() {
echo
echo "Stopping services..."
pkill -P "$FASTAPI_PID" 2>/dev/null || true
pkill -P "$NEXTJS_PID" 2>/dev/null || true
kill "$FASTAPI_PID" 2>/dev/null || true
kill "$NEXTJS_PID" 2>/dev/null || true
if [[ -n "$MCP_PID" ]]; then
pkill -P "$MCP_PID" 2>/dev/null || true
kill "$MCP_PID" 2>/dev/null || true
fi
}
trap cleanup INT TERM EXIT
# Portable process supervision (works with macOS bash 3.2)
while true; do
if ! kill -0 "$FASTAPI_PID" 2>/dev/null; then
echo "FastAPI exited."
break
fi
if ! kill -0 "$NEXTJS_PID" 2>/dev/null; then
echo "Next.js exited."
break
fi
if [[ -n "$MCP_PID" ]] && ! kill -0 "$MCP_PID" 2>/dev/null; then
echo "MCP server exited."
break
fi
sleep 1
done