Consolidate Reports and Data Entry apps into a single Vue.js SPA with: Architecture: - Module-based structure with lazy-loaded routes (@reports, @data-entry) - Error boundaries per module to prevent cascade failures - Dual API proxy in Vite for microservices (reports:8001, data-entry:8003) - Pinia store factories for shared auth, company, and period stores - Vite path aliases for clear module boundaries (@shared, @reports, @data-entry) Service Management: - Granular service control scripts (backend-reports.sh, backend-data-entry.sh, bot.sh, frontend.sh) - 87% faster frontend restart: 7s vs 53s full restart - 38% faster full startup: 33s vs 53s via parallel backend initialization - Enhanced start-dev.sh with proper service timeouts (OCR: 30s, Vite: 15s, Bot: 10s) - status.sh for comprehensive health checks Features: - Auto-select first company on login with period auto-load - Hamburger menu with feature toggle support - JWT token auto-injection via axios interceptors - Unified header with company/period selectors - IIS web.config for production deployment with multi-API routing UX Improvements: - Vue watchers for reactive company/period loading - Lazy store initialization with graceful error handling - Period persistence per user+company in localStorage - Feature flags for optional modules Deployment: - Single IIS site serves unified frontend with API proxy rules - Maintains separate backend processes for microservices - Windows line ending fixes (.env CRLF → LF conversion) Stats: 112 files changed, 38,342 insertions(+), 2,342 deletions(-) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
171 lines
4.8 KiB
Bash
171 lines
4.8 KiB
Bash
#!/bin/bash
|
||
# Service Helper Functions for ROA2WEB Unified App
|
||
# Shared functions for service management scripts
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Wait for a port to become available
|
||
# Usage: wait_for_port <port> <service_name> [timeout_seconds]
|
||
wait_for_port() {
|
||
local port=$1
|
||
local service_name=$2
|
||
local timeout=${3:-30}
|
||
local elapsed=0
|
||
local interval=1
|
||
|
||
echo -e "${BLUE}⏳ Waiting for ${service_name} on port ${port}...${NC}"
|
||
|
||
while [ $elapsed -lt $timeout ]; do
|
||
if netstat -tuln 2>/dev/null | grep -q ":${port} " || ss -tuln 2>/dev/null | grep -q ":${port} "; then
|
||
echo -e "${GREEN}✓ ${service_name} is ready on port ${port}${NC}"
|
||
return 0
|
||
fi
|
||
sleep $interval
|
||
elapsed=$((elapsed + interval))
|
||
done
|
||
|
||
echo -e "${RED}✗ Timeout waiting for ${service_name} on port ${port}${NC}"
|
||
return 1
|
||
}
|
||
|
||
# Kill process on a specific port
|
||
# Usage: kill_port <port> <service_name>
|
||
kill_port() {
|
||
local port=$1
|
||
local service_name=$2
|
||
|
||
echo -e "${YELLOW}🛑 Stopping ${service_name} on port ${port}...${NC}"
|
||
|
||
# Try lsof first
|
||
if command -v lsof &> /dev/null; then
|
||
local pids=$(lsof -ti:${port} 2>/dev/null)
|
||
if [ -n "$pids" ]; then
|
||
echo "$pids" | xargs kill -KILL 2>/dev/null
|
||
sleep 1
|
||
echo -e "${GREEN}✓ ${service_name} stopped${NC}"
|
||
return 0
|
||
fi
|
||
fi
|
||
|
||
# Fallback to netstat/ss
|
||
local pids=$(netstat -tlnp 2>/dev/null | grep ":${port} " | awk '{print $7}' | cut -d'/' -f1)
|
||
if [ -z "$pids" ]; then
|
||
pids=$(ss -tlnp 2>/dev/null | grep ":${port} " | grep -oP 'pid=\K[0-9]+')
|
||
fi
|
||
|
||
if [ -n "$pids" ]; then
|
||
echo "$pids" | xargs kill -KILL 2>/dev/null
|
||
sleep 1
|
||
echo -e "${GREEN}✓ ${service_name} stopped${NC}"
|
||
return 0
|
||
fi
|
||
|
||
echo -e "${YELLOW}⚠ No process found on port ${port}${NC}"
|
||
return 0
|
||
}
|
||
|
||
# Check if a service is running on a port
|
||
# Usage: check_service_status <port> <service_name>
|
||
check_service_status() {
|
||
local port=$1
|
||
local service_name=$2
|
||
|
||
if netstat -tuln 2>/dev/null | grep -q ":${port} " || ss -tuln 2>/dev/null | grep -q ":${port} "; then
|
||
echo -e "${GREEN}✓ ${service_name} is RUNNING on port ${port}${NC}"
|
||
|
||
# Try to get process info
|
||
if command -v lsof &> /dev/null; then
|
||
local pid=$(lsof -ti:${port} 2>/dev/null | head -1)
|
||
if [ -n "$pid" ]; then
|
||
echo -e " ${BLUE}PID: ${pid}${NC}"
|
||
local cmd=$(ps -p $pid -o comm= 2>/dev/null)
|
||
if [ -n "$cmd" ]; then
|
||
echo -e " ${BLUE}Command: ${cmd}${NC}"
|
||
fi
|
||
fi
|
||
fi
|
||
return 0
|
||
else
|
||
echo -e "${RED}✗ ${service_name} is NOT running (port ${port} not in use)${NC}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Tail logs with error highlighting
|
||
# Usage: tail_logs <log_file> [lines]
|
||
tail_logs() {
|
||
local log_file=$1
|
||
local lines=${2:-20}
|
||
|
||
if [ ! -f "$log_file" ]; then
|
||
echo -e "${RED}✗ Log file not found: ${log_file}${NC}"
|
||
return 1
|
||
fi
|
||
|
||
echo -e "${BLUE}📄 Last ${lines} lines from ${log_file}:${NC}"
|
||
echo "─────────────────────────────────────────"
|
||
|
||
# Highlight errors in red
|
||
tail -n $lines "$log_file" | sed -e "s/ERROR/${RED}ERROR${NC}/g" \
|
||
-e "s/CRITICAL/${RED}CRITICAL${NC}/g" \
|
||
-e "s/WARNING/${YELLOW}WARNING${NC}/g" \
|
||
-e "s/INFO/${GREEN}INFO${NC}/g"
|
||
|
||
echo "─────────────────────────────────────────"
|
||
}
|
||
|
||
# Check if port is already in use
|
||
# Usage: check_port_available <port> <service_name>
|
||
# Returns 0 if port is FREE, 1 if OCCUPIED
|
||
check_port_available() {
|
||
local port=$1
|
||
local service_name=$2
|
||
|
||
if netstat -tuln 2>/dev/null | grep -q ":${port} " || ss -tuln 2>/dev/null | grep -q ":${port} "; then
|
||
echo -e "${YELLOW}⚠ Port ${port} is already in use (${service_name} may already be running)${NC}"
|
||
return 1
|
||
else
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# Display a nice header
|
||
# Usage: print_header "Title"
|
||
print_header() {
|
||
local title=$1
|
||
echo ""
|
||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
||
echo -e "${BLUE} ${title}${NC}"
|
||
echo -e "${BLUE}════════════════════════════════════════${NC}"
|
||
echo ""
|
||
}
|
||
|
||
# Display success message
|
||
# Usage: print_success "Message"
|
||
print_success() {
|
||
echo -e "${GREEN}✓ $1${NC}"
|
||
}
|
||
|
||
# Display error message
|
||
# Usage: print_error "Message"
|
||
print_error() {
|
||
echo -e "${RED}✗ $1${NC}"
|
||
}
|
||
|
||
# Display warning message
|
||
# Usage: print_warning "Message"
|
||
print_warning() {
|
||
echo -e "${YELLOW}⚠ $1${NC}"
|
||
}
|
||
|
||
# Display info message
|
||
# Usage: print_info "Message"
|
||
print_info() {
|
||
echo -e "${BLUE}ℹ $1${NC}"
|
||
}
|