1+ #! /bin/bash
2+ # Unified cross-platform development script
3+ # Works on Unix/Linux/macOS and Windows (via Git Bash/WSL/MSYS2)
4+
5+ set -e
6+
7+ # Get script directory and project root
8+ SCRIPT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " & > /dev/null && pwd ) "
9+ PROJECT_ROOT=" $( dirname " $SCRIPT_DIR " ) "
10+
11+ # Enhanced OS detection
12+ detect_os () {
13+ local os=" unknown"
14+ local is_wsl=false
15+ local shell_env=" unknown"
16+
17+ # Detect operating system
18+ case " $( uname -s) " in
19+ Linux* )
20+ if [[ -n " ${WSL_DISTRO_NAME:- } " ]] || [[ " $( uname -r) " == * microsoft* ]]; then
21+ os=" wsl"
22+ is_wsl=true
23+ else
24+ os=" linux"
25+ fi
26+ ;;
27+ Darwin* ) os=" macos" ;;
28+ CYGWIN* ) os=" windows-cygwin" ;;
29+ MINGW* ) os=" windows-mingw" ;;
30+ MSYS* ) os=" windows-msys" ;;
31+ * ) os=" unknown" ;;
32+ esac
33+
34+ # Detect shell environment
35+ if [[ -n " ${BASH_VERSION:- } " ]]; then
36+ shell_env=" bash"
37+ elif [[ -n " ${ZSH_VERSION:- } " ]]; then
38+ shell_env=" zsh"
39+ else
40+ shell_env=" sh"
41+ fi
42+
43+ echo " $os |$is_wsl |$shell_env "
44+ }
45+
46+ # Parse OS detection
47+ OS_INFO=$( detect_os)
48+ OS=$( echo " $OS_INFO " | cut -d' |' -f1)
49+ IS_WSL=$( echo " $OS_INFO " | cut -d' |' -f2)
50+ SHELL_ENV=$( echo " $OS_INFO " | cut -d' |' -f3)
51+
52+ # Determine if we're on Windows-like environment
53+ case " $OS " in
54+ windows-* |wsl) IS_WINDOWS_LIKE=true;;
55+ * ) IS_WINDOWS_LIKE=false;;
56+ esac
57+
58+ # Colors for output (with Windows compatibility)
59+ if [[ " $IS_WINDOWS_LIKE " == " true" ]] && [[ " $OS " != " wsl" ]]; then
60+ # Limited color support on Windows
61+ RED=" "
62+ GREEN=" "
63+ YELLOW=" "
64+ NC=" "
65+ else
66+ RED=' \033[0;31m'
67+ GREEN=' \033[0;32m'
68+ YELLOW=' \033[1;33m'
69+ NC=' \033[0m'
70+ fi
71+
72+ print_header () {
73+ echo -e " ${GREEN} 🚄 Hyperloop H10 Development Environment${NC} "
74+ echo -e " ${GREEN} =======================================${NC} "
75+ echo -e " ${YELLOW} OS: $OS ${NC} "
76+ echo -e " ${YELLOW} Shell: $SHELL_ENV ${NC} "
77+ echo -e " ${YELLOW} WSL: $IS_WSL ${NC} "
78+ echo " "
79+ }
80+
81+ print_usage () {
82+ echo " Usage: $0 [command]"
83+ echo " "
84+ echo " Commands:"
85+ echo " setup - Install all dependencies"
86+ echo " backend - Run backend server"
87+ echo " ethernet - Run ethernet-view dev server"
88+ echo " control - Run control-station dev server"
89+ echo " packet - Run packet-sender"
90+ echo " all - Run all services"
91+ echo " test - Run all tests"
92+ echo " build - Build all components"
93+ echo " "
94+ echo " Platform Notes:"
95+ if [[ " $IS_WINDOWS_LIKE " == " true" ]]; then
96+ echo " - Windows detected: Services will run in parallel processes"
97+ echo " - Use Ctrl+C to stop all services when running 'all' command"
98+ else
99+ echo " - Unix-like system: 'all' command uses tmux if available"
100+ echo " - Install tmux for better multi-service management"
101+ fi
102+ echo " "
103+ }
104+
105+ check_dependencies () {
106+ local missing=()
107+
108+ command -v go > /dev/null 2>&1 || missing+=(" go" )
109+ command -v node > /dev/null 2>&1 || missing+=(" node" )
110+ command -v npm > /dev/null 2>&1 || missing+=(" npm" )
111+
112+ if [ ${# missing[@]} -ne 0 ]; then
113+ echo -e " ${RED} Error: Missing required dependencies: ${missing[*]}${NC} "
114+ echo " Please install them before continuing."
115+ echo " "
116+ echo " Installation guides:"
117+ echo " Go: https://golang.org/doc/install"
118+ echo " Node.js: https://nodejs.org/"
119+ exit 1
120+ fi
121+
122+ echo -e " ${GREEN} ✅ All dependencies found${NC} "
123+ }
124+
125+ # Convert Windows paths if needed
126+ normalize_path () {
127+ local path=" $1 "
128+ if [[ " $IS_WINDOWS_LIKE " == " true" ]] && [[ " $OS " != " wsl" ]]; then
129+ echo " $path " | sed ' s|/|\\|g'
130+ else
131+ echo " $path "
132+ fi
133+ }
134+
135+ # Cross-platform directory change
136+ safe_cd () {
137+ local target_dir=" $1 "
138+ local normalized_dir
139+ normalized_dir=$( normalize_path " $target_dir " )
140+
141+ if ! cd " $normalized_dir " 2> /dev/null; then
142+ echo -e " ${RED} Error: Cannot change to directory: $normalized_dir ${NC} "
143+ exit 1
144+ fi
145+ }
146+
147+ setup_project () {
148+ echo -e " ${YELLOW} Setting up project dependencies...${NC} "
149+
150+ safe_cd " $PROJECT_ROOT "
151+
152+ # Build common-front first
153+ echo " 📦 Building common-front..."
154+ safe_cd " $PROJECT_ROOT /common-front"
155+ npm install
156+ npm run build
157+
158+ # Install ethernet-view dependencies
159+ echo " 📦 Installing ethernet-view dependencies..."
160+ safe_cd " $PROJECT_ROOT /ethernet-view"
161+ npm install
162+
163+ # Install control-station dependencies
164+ echo " 📦 Installing control-station dependencies..."
165+ safe_cd " $PROJECT_ROOT /control-station"
166+ npm install
167+
168+ # Download Go dependencies
169+ echo " 📦 Downloading Go dependencies..."
170+ safe_cd " $PROJECT_ROOT /backend"
171+ go mod download
172+
173+ safe_cd " $PROJECT_ROOT /packet-sender"
174+ go mod download
175+
176+ echo -e " ${GREEN} ✅ Setup complete!${NC} "
177+ }
178+
179+ run_backend () {
180+ safe_cd " $PROJECT_ROOT /backend/cmd"
181+ echo -e " ${YELLOW} Starting backend server...${NC} "
182+ go run .
183+ }
184+
185+ run_ethernet_view () {
186+ safe_cd " $PROJECT_ROOT /ethernet-view"
187+ echo -e " ${YELLOW} Starting ethernet-view dev server...${NC} "
188+ npm run dev
189+ }
190+
191+ run_control_station () {
192+ safe_cd " $PROJECT_ROOT /control-station"
193+ echo -e " ${YELLOW} Starting control-station dev server...${NC} "
194+ npm run dev
195+ }
196+
197+ run_packet_sender () {
198+ safe_cd " $PROJECT_ROOT /packet-sender"
199+ echo -e " ${YELLOW} Starting packet-sender...${NC} "
200+ go run .
201+ }
202+
203+ run_all_services () {
204+ if [[ " $IS_WINDOWS_LIKE " == " true" ]] && [[ " $OS " != " wsl" ]]; then
205+ echo -e " ${YELLOW} Running all services in parallel (Windows mode)...${NC} "
206+ echo -e " ${YELLOW} Use Ctrl+C to stop all services${NC} "
207+ echo " "
208+
209+ # Start all services in background
210+ (safe_cd " $PROJECT_ROOT /backend/cmd" && go run .) &
211+ PID_BACKEND=$!
212+
213+ (safe_cd " $PROJECT_ROOT /ethernet-view" && npm run dev) &
214+ PID_ETHERNET=$!
215+
216+ (safe_cd " $PROJECT_ROOT /control-station" && npm run dev) &
217+ PID_CONTROL=$!
218+
219+ (safe_cd " $PROJECT_ROOT /packet-sender" && go run .) &
220+ PID_PACKET=$!
221+
222+ echo -e " ${GREEN} All services started. PIDs: Backend=$PID_BACKEND , Ethernet=$PID_ETHERNET , Control=$PID_CONTROL , Packet=$PID_PACKET ${NC} "
223+
224+ # Function to cleanup on exit
225+ cleanup () {
226+ echo -e " ${YELLOW} Stopping all services...${NC} "
227+ kill $PID_BACKEND $PID_ETHERNET $PID_CONTROL $PID_PACKET 2> /dev/null || true
228+ exit
229+ }
230+
231+ # Set trap for cleanup
232+ trap cleanup SIGINT SIGTERM
233+
234+ # Wait for any process to exit
235+ wait
236+
237+ else
238+ # Unix-like system - prefer tmux if available
239+ if command -v tmux > /dev/null 2>&1 ; then
240+ run_all_tmux
241+ else
242+ echo -e " ${YELLOW} tmux not found. Running services in parallel...${NC} "
243+ echo -e " ${YELLOW} Use Ctrl+C to stop all services${NC} "
244+ echo " "
245+
246+ # Fallback to background processes
247+ (safe_cd " $PROJECT_ROOT /backend/cmd" && go run .) &
248+ PID_BACKEND=$!
249+
250+ (safe_cd " $PROJECT_ROOT /ethernet-view" && npm run dev) &
251+ PID_ETHERNET=$!
252+
253+ (safe_cd " $PROJECT_ROOT /control-station" && npm run dev) &
254+ PID_CONTROL=$!
255+
256+ (safe_cd " $PROJECT_ROOT /packet-sender" && go run .) &
257+ PID_PACKET=$!
258+
259+ echo -e " ${GREEN} All services started. PIDs: Backend=$PID_BACKEND , Ethernet=$PID_ETHERNET , Control=$PID_CONTROL , Packet=$PID_PACKET ${NC} "
260+ echo -e " ${YELLOW} Tip: Install tmux for better session management${NC} "
261+
262+ # Function to cleanup on exit
263+ cleanup () {
264+ echo -e " ${YELLOW} Stopping all services...${NC} "
265+ kill $PID_BACKEND $PID_ETHERNET $PID_CONTROL $PID_PACKET 2> /dev/null || true
266+ exit
267+ }
268+
269+ # Set trap for cleanup
270+ trap cleanup SIGINT SIGTERM
271+
272+ # Wait for any process to exit
273+ wait
274+ fi
275+ fi
276+ }
277+
278+ run_all_tmux () {
279+ SESSION=" hyperloop-dev"
280+
281+ # Kill existing session if it exists
282+ tmux kill-session -t $SESSION 2> /dev/null || true
283+
284+ # Create new session with backend
285+ tmux new-session -d -s $SESSION -n backend " cd '$PROJECT_ROOT /backend/cmd' && go run ."
286+
287+ # Create windows for other services
288+ tmux new-window -t $SESSION -n ethernet-view " cd '$PROJECT_ROOT /ethernet-view' && npm run dev"
289+ tmux new-window -t $SESSION -n control-station " cd '$PROJECT_ROOT /control-station' && npm run dev"
290+ tmux new-window -t $SESSION -n packet-sender " cd '$PROJECT_ROOT /packet-sender' && go run ."
291+
292+ # Attach to session
293+ echo -e " ${GREEN} Starting all services in tmux session '$SESSION '${NC} "
294+ echo -e " ${YELLOW} Use 'tmux attach -t $SESSION ' to reconnect${NC} "
295+ tmux attach-session -t $SESSION
296+ }
297+
298+ run_tests () {
299+ echo -e " ${YELLOW} Running tests...${NC} "
300+
301+ safe_cd " $PROJECT_ROOT /backend"
302+ echo " 🧪 Running backend tests..."
303+ go test -v ./...
304+
305+ echo -e " ${GREEN} ✅ All tests completed${NC} "
306+ }
307+
308+ build_all () {
309+ safe_cd " $PROJECT_ROOT "
310+ echo -e " ${YELLOW} Building all components...${NC} "
311+
312+ # Check if make is available
313+ if command -v make > /dev/null 2>&1 ; then
314+ make all
315+ else
316+ echo -e " ${YELLOW} Make not found, building components individually...${NC} "
317+
318+ # Build backend
319+ echo " Building backend..."
320+ safe_cd " $PROJECT_ROOT /backend"
321+ go build -o backend cmd/main.go cmd/config.go cmd/pid.go cmd/trace.go
322+
323+ # Build common-front
324+ echo " Building common-front..."
325+ safe_cd " $PROJECT_ROOT /common-front"
326+ npm run build
327+
328+ # Build other frontends
329+ echo " Building ethernet-view..."
330+ safe_cd " $PROJECT_ROOT /ethernet-view"
331+ npm run build
332+
333+ echo " Building control-station..."
334+ safe_cd " $PROJECT_ROOT /control-station"
335+ npm run build
336+ fi
337+
338+ echo -e " ${GREEN} ✅ Build complete!${NC} "
339+ }
340+
341+ # Main script logic
342+ print_header
343+ check_dependencies
344+
345+ case " ${1:- } " in
346+ setup)
347+ setup_project
348+ ;;
349+ backend)
350+ run_backend
351+ ;;
352+ ethernet)
353+ run_ethernet_view
354+ ;;
355+ control)
356+ run_control_station
357+ ;;
358+ packet)
359+ run_packet_sender
360+ ;;
361+ all)
362+ run_all_services
363+ ;;
364+ test)
365+ run_tests
366+ ;;
367+ build)
368+ build_all
369+ ;;
370+ " " )
371+ print_usage
372+ ;;
373+ * )
374+ echo -e " ${RED} Unknown command: $1 ${NC} "
375+ print_usage
376+ exit 1
377+ ;;
378+ esac
0 commit comments