You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							398 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							398 lines
						
					
					
						
							12 KiB
						
					
					
				
								#!/bin/bash
							 | 
						|
								# build-web.sh
							 | 
						|
								# Author: Matthew Raymer
							 | 
						|
								# Description: Web build script for TimeSafari application
							 | 
						|
								# This script handles the complete web build process including cleanup,
							 | 
						|
								# environment setup, Vite build, and optional Docker containerization.
							 | 
						|
								#
							 | 
						|
								# Usage:
							 | 
						|
								#   ./scripts/build-web.sh                    # Development build
							 | 
						|
								#   ./scripts/build-web.sh --dev              # Development build (explicit)
							 | 
						|
								#   ./scripts/build-web.sh --test             # Test environment build
							 | 
						|
								#   ./scripts/build-web.sh --prod             # Production environment build
							 | 
						|
								#   ./scripts/build-web.sh --docker           # Build with Docker containerization
							 | 
						|
								#   ./scripts/build-web.sh --docker:test      # Test environment + Docker
							 | 
						|
								#   ./scripts/build-web.sh --docker:prod      # Production environment + Docker
							 | 
						|
								#   ./scripts/build-web.sh --serve            # Build and serve locally
							 | 
						|
								#   ./scripts/build-web.sh --help             # Show help
							 | 
						|
								#   ./scripts/build-web.sh --verbose          # Enable verbose logging
							 | 
						|
								#
							 | 
						|
								# NPM Script Equivalents:
							 | 
						|
								#   npm run build:web                         # Development build
							 | 
						|
								#   npm run build:web:test                    # Test environment build
							 | 
						|
								#   npm run build:web:prod                    # Production environment build
							 | 
						|
								#   npm run build:web:docker                  # Docker build
							 | 
						|
								#   npm run build:web:docker:test             # Test Docker build
							 | 
						|
								#   npm run build:web:docker:prod             # Production Docker build
							 | 
						|
								#
							 | 
						|
								# Exit Codes:
							 | 
						|
								# 1 - Web cleanup failed
							 | 
						|
								# 2 - Environment setup failed
							 | 
						|
								# 3 - Vite build failed
							 | 
						|
								# 4 - Docker build failed
							 | 
						|
								# 5 - Serve command failed
							 | 
						|
								# 6 - Invalid build mode
							 | 
						|
								
							 | 
						|
								# Exit on any error
							 | 
						|
								set -e
							 | 
						|
								
							 | 
						|
								# Source common utilities
							 | 
						|
								source "$(dirname "$0")/common.sh"
							 | 
						|
								
							 | 
						|
								# Default values
							 | 
						|
								BUILD_MODE="development"
							 | 
						|
								BUILD_ACTION="build"
							 | 
						|
								DOCKER_BUILD=false
							 | 
						|
								SERVE_BUILD=false
							 | 
						|
								
							 | 
						|
								# Function to show usage
							 | 
						|
								show_usage() {
							 | 
						|
								    cat << EOF
							 | 
						|
								Usage: $0 [OPTIONS]
							 | 
						|
								
							 | 
						|
								OPTIONS:
							 | 
						|
								    --dev, --development    Build for development environment (default)
							 | 
						|
								    --test                  Build for test environment
							 | 
						|
								    --prod, --production    Build for production environment
							 | 
						|
								    --docker                Build and create Docker container
							 | 
						|
								    --docker:test           Build for test environment and create Docker container
							 | 
						|
								    --docker:prod           Build for production environment and create Docker container
							 | 
						|
								    --serve                 Build and serve locally
							 | 
						|
								    --help                  Show this help message
							 | 
						|
								    --verbose               Enable verbose logging
							 | 
						|
								    --env                   Show environment variables
							 | 
						|
								
							 | 
						|
								EXAMPLES:
							 | 
						|
								    $0                                   # Development build
							 | 
						|
								    $0 --test                            # Test environment build
							 | 
						|
								    $0 --prod                            # Production environment build
							 | 
						|
								    $0 --docker                          # Development + Docker
							 | 
						|
								    $0 --docker:test                     # Test + Docker
							 | 
						|
								    $0 --docker:prod                     # Production + Docker
							 | 
						|
								    $0 --serve                           # Build and serve
							 | 
						|
								
							 | 
						|
								BUILD MODES:
							 | 
						|
								    development: Starts Vite development server with hot reload (default)
							 | 
						|
								    test: Optimized for testing with minimal minification
							 | 
						|
								    production: Optimized for production with full minification and optimization
							 | 
						|
								
							 | 
						|
								EOF
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to parse web-specific arguments
							 | 
						|
								parse_web_args() {
							 | 
						|
								    while [[ $# -gt 0 ]]; do
							 | 
						|
								        case $1 in
							 | 
						|
								            --dev|--development)
							 | 
						|
								                BUILD_MODE="development"
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --test)
							 | 
						|
								                BUILD_MODE="test"
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --prod|--production)
							 | 
						|
								                BUILD_MODE="production"
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --docker)
							 | 
						|
								                DOCKER_BUILD=true
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --docker:test)
							 | 
						|
								                BUILD_MODE="test"
							 | 
						|
								                DOCKER_BUILD=true
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --docker:prod)
							 | 
						|
								                BUILD_MODE="production"
							 | 
						|
								                DOCKER_BUILD=true
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --serve)
							 | 
						|
								                SERVE_BUILD=true
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --help)
							 | 
						|
								                show_usage
							 | 
						|
								                exit 0
							 | 
						|
								                ;;
							 | 
						|
								            --verbose)
							 | 
						|
								                VERBOSE=true
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								            --env)
							 | 
						|
								                print_env_vars "VITE_"
							 | 
						|
								                exit 0
							 | 
						|
								                ;;
							 | 
						|
								            *)
							 | 
						|
								                log_warn "Unknown option: $1"
							 | 
						|
								                shift
							 | 
						|
								                ;;
							 | 
						|
								        esac
							 | 
						|
								    done
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to validate web build environment
							 | 
						|
								validate_web_environment() {
							 | 
						|
								    log_info "Validating web build environment..."
							 | 
						|
								    
							 | 
						|
								    # Check if Node.js is available
							 | 
						|
								    if ! check_command "node"; then
							 | 
						|
								        log_error "Node.js is required but not installed"
							 | 
						|
								        exit 2
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check if npm is available
							 | 
						|
								    if ! check_command "npm"; then
							 | 
						|
								        log_error "npm is required but not installed"
							 | 
						|
								        exit 2
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check if Vite is available
							 | 
						|
								    if ! check_command "npx"; then
							 | 
						|
								        log_error "npx is required but not installed"
							 | 
						|
								        exit 2
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Check if package.json exists
							 | 
						|
								    if ! check_file "package.json"; then
							 | 
						|
								        log_error "package.json not found in current directory"
							 | 
						|
								        exit 2
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "Web build environment validated"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to setup web-specific environment
							 | 
						|
								setup_web_environment() {
							 | 
						|
								    log_info "Setting up web environment for $BUILD_MODE mode..."
							 | 
						|
								    
							 | 
						|
								    # Set NODE_ENV based on build mode
							 | 
						|
								    case $BUILD_MODE in
							 | 
						|
								        "production")
							 | 
						|
								            export NODE_ENV="production"
							 | 
						|
								            ;;
							 | 
						|
								        "test")
							 | 
						|
								            export NODE_ENV="test"
							 | 
						|
								            ;;
							 | 
						|
								        "development"|*)
							 | 
						|
								            export NODE_ENV="development"
							 | 
						|
								            ;;
							 | 
						|
								    esac
							 | 
						|
								    
							 | 
						|
								    # Load environment-specific .env file if it exists
							 | 
						|
								    local env_file=".env.$BUILD_MODE"
							 | 
						|
								    if [ -f "$env_file" ]; then
							 | 
						|
								        load_env_file "$env_file"
							 | 
						|
								    else
							 | 
						|
								        log_debug "No $env_file file found, using default environment"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Load .env file if it exists (fallback)
							 | 
						|
								    if [ -f ".env" ]; then
							 | 
						|
								        load_env_file ".env"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "Web environment configured for $BUILD_MODE mode"
							 | 
						|
								    log_debug "NODE_ENV=$NODE_ENV"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to execute Vite build
							 | 
						|
								execute_vite_build() {
							 | 
						|
								    local mode="$1"
							 | 
						|
								    log_info "Executing Vite build for $mode mode..."
							 | 
						|
								    
							 | 
						|
								    # Construct Vite build command
							 | 
						|
								    local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite build --config vite.config.web.mts"
							 | 
						|
								    
							 | 
						|
								    # Add mode if not development (development is default)
							 | 
						|
								    if [ "$mode" != "development" ]; then
							 | 
						|
								        vite_cmd="$vite_cmd --mode $mode"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_debug "Vite command: $vite_cmd"
							 | 
						|
								    
							 | 
						|
								    if ! measure_time eval "$vite_cmd"; then
							 | 
						|
								        log_error "Vite build failed for $mode mode!"
							 | 
						|
								        exit 3
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "Vite build completed for $mode mode"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to execute Docker build
							 | 
						|
								execute_docker_build() {
							 | 
						|
								    local mode="$1"
							 | 
						|
								    log_info "Executing Docker build for $mode mode..."
							 | 
						|
								    
							 | 
						|
								    # Build Docker image with appropriate tags
							 | 
						|
								    local docker_cmd="docker build"
							 | 
						|
								    local image_tag="timesafari-web"
							 | 
						|
								    
							 | 
						|
								    # Add build arguments
							 | 
						|
								    docker_cmd="$docker_cmd --build-arg BUILD_MODE=$mode"
							 | 
						|
								    docker_cmd="$docker_cmd --build-arg NODE_ENV=$NODE_ENV"
							 | 
						|
								    
							 | 
						|
								    # Add image tag
							 | 
						|
								    docker_cmd="$docker_cmd -t $image_tag:$mode"
							 | 
						|
								    docker_cmd="$docker_cmd -t $image_tag:latest"
							 | 
						|
								    
							 | 
						|
								    # Add context
							 | 
						|
								    docker_cmd="$docker_cmd ."
							 | 
						|
								    
							 | 
						|
								    log_debug "Docker command: $docker_cmd"
							 | 
						|
								    
							 | 
						|
								    if ! measure_time eval "$docker_cmd"; then
							 | 
						|
								        log_error "Docker build failed for $mode mode!"
							 | 
						|
								        exit 4
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_success "Docker build completed for $mode mode"
							 | 
						|
								    log_info "Docker image available as: $image_tag:$mode"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to run type checking based on build mode
							 | 
						|
								run_type_checking() {
							 | 
						|
								    local mode="$1"
							 | 
						|
								    
							 | 
						|
								    # Only run type checking for production and test builds
							 | 
						|
								    if [ "$mode" = "production" ] || [ "$mode" = "test" ]; then
							 | 
						|
								        log_info "Running TypeScript type checking for $mode mode..."
							 | 
						|
								        
							 | 
						|
								        if ! measure_time npm run type-check; then
							 | 
						|
								            log_error "TypeScript type checking failed for $mode mode!"
							 | 
						|
								            exit 2
							 | 
						|
								        fi
							 | 
						|
								        
							 | 
						|
								        log_success "TypeScript type checking completed for $mode mode"
							 | 
						|
								    else
							 | 
						|
								        log_debug "Skipping TypeScript type checking for development mode"
							 | 
						|
								    fi
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to start Vite development server
							 | 
						|
								start_dev_server() {
							 | 
						|
								    log_info "Starting Vite development server..."
							 | 
						|
								    
							 | 
						|
								    # Construct Vite dev server command
							 | 
						|
								    local vite_cmd="VITE_GIT_HASH=\$(git log -1 --pretty=format:%h) npx vite --config vite.config.web.mts"
							 | 
						|
								    
							 | 
						|
								    # Add mode if specified (though development is default)
							 | 
						|
								    if [ "$BUILD_MODE" != "development" ]; then
							 | 
						|
								        vite_cmd="$vite_cmd --mode $BUILD_MODE"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    log_debug "Vite dev server command: $vite_cmd"
							 | 
						|
								    log_info "Starting development server on http://localhost:8080"
							 | 
						|
								    
							 | 
						|
								    # Start the development server (this will block and run the server)
							 | 
						|
								    eval "$vite_cmd"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Function to serve build locally
							 | 
						|
								serve_build() {
							 | 
						|
								    log_info "Serving build locally..."
							 | 
						|
								    
							 | 
						|
								    # Check if dist directory exists
							 | 
						|
								    if [ ! -d "dist" ]; then
							 | 
						|
								        log_error "dist directory not found. Build must be completed first."
							 | 
						|
								        exit 5
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Use a server that supports SPA routing (serves index.html for all routes)
							 | 
						|
								    if command -v npx &> /dev/null; then
							 | 
						|
								        log_info "Starting npx serve with SPA support on port 8080..."
							 | 
						|
								        npx serve -s dist -l 8080
							 | 
						|
								    elif command -v python3 &> /dev/null; then
							 | 
						|
								        log_warn "Python HTTP server doesn't support SPA routing. Routes like /discover, /account will return 404."
							 | 
						|
								        log_info "Starting Python HTTP server on port 8080..."
							 | 
						|
								        cd dist && python3 -m http.server 8080
							 | 
						|
								    elif command -v python &> /dev/null; then
							 | 
						|
								        log_warn "Python HTTP server doesn't support SPA routing. Routes like /discover, /account will return 404."
							 | 
						|
								        log_info "Starting Python HTTP server on port 8080..."
							 | 
						|
								        cd dist && python -m SimpleHTTPServer 8080
							 | 
						|
								    else
							 | 
						|
								        log_error "No suitable HTTP server found. Install npx serve or Python."
							 | 
						|
								        exit 5
							 | 
						|
								    fi
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								# Parse command line arguments
							 | 
						|
								parse_web_args "$@"
							 | 
						|
								
							 | 
						|
								# Print build header
							 | 
						|
								print_header "TimeSafari Web Build Process"
							 | 
						|
								log_info "Starting web build process at $(date)"
							 | 
						|
								log_info "Build mode: $BUILD_MODE"
							 | 
						|
								log_info "Docker build: $DOCKER_BUILD"
							 | 
						|
								log_info "Serve build: $SERVE_BUILD"
							 | 
						|
								
							 | 
						|
								# Validate environment
							 | 
						|
								validate_web_environment
							 | 
						|
								
							 | 
						|
								# Setup environment for web build
							 | 
						|
								setup_build_env "web" "$BUILD_MODE"
							 | 
						|
								
							 | 
						|
								# Setup application directories
							 | 
						|
								setup_app_directories
							 | 
						|
								
							 | 
						|
								# Setup web-specific environment
							 | 
						|
								setup_web_environment
							 | 
						|
								
							 | 
						|
								# Handle different build modes
							 | 
						|
								if [ "$BUILD_MODE" = "development" ] && [ "$DOCKER_BUILD" = false ] && [ "$SERVE_BUILD" = false ]; then
							 | 
						|
								    # Development mode: Start dev server
							 | 
						|
								    log_info "Development mode detected - starting development server"
							 | 
						|
								    start_dev_server
							 | 
						|
								    # Note: start_dev_server doesn't return, it runs the server
							 | 
						|
								elif [ "$SERVE_BUILD" = true ]; then
							 | 
						|
								    # Serve mode: Build then serve
							 | 
						|
								    log_info "Serve mode detected - building then serving"
							 | 
						|
								    
							 | 
						|
								    # Step 1: Clean dist directory
							 | 
						|
								    log_info "Cleaning dist directory..."
							 | 
						|
								    clean_build_artifacts "dist"
							 | 
						|
								    
							 | 
						|
								    # Step 2: Run type checking (for production/test builds)
							 | 
						|
								    safe_execute "Type checking for $BUILD_MODE mode" "run_type_checking $BUILD_MODE" || exit 2
							 | 
						|
								    
							 | 
						|
								    # Step 3: Execute Vite build
							 | 
						|
								    safe_execute "Vite build for $BUILD_MODE mode" "execute_vite_build $BUILD_MODE" || exit 3
							 | 
						|
								    
							 | 
						|
								    # Step 3: Serve the build
							 | 
						|
								    log_info "Starting local server..."
							 | 
						|
								    serve_build
							 | 
						|
								    # Note: serve_build doesn't return, it starts the server
							 | 
						|
								else
							 | 
						|
								    # Build mode: Build (and optionally Docker)
							 | 
						|
								    log_info "Build mode detected - building for $BUILD_MODE"
							 | 
						|
								    
							 | 
						|
								    # Step 1: Clean dist directory
							 | 
						|
								    log_info "Cleaning dist directory..."
							 | 
						|
								    clean_build_artifacts "dist"
							 | 
						|
								    
							 | 
						|
								    # Step 2: Run type checking (for production/test builds)
							 | 
						|
								    safe_execute "Type checking for $BUILD_MODE mode" "run_type_checking $BUILD_MODE" || exit 2
							 | 
						|
								    
							 | 
						|
								    # Step 3: Execute Vite build
							 | 
						|
								    safe_execute "Vite build for $BUILD_MODE mode" "execute_vite_build $BUILD_MODE" || exit 3
							 | 
						|
								    
							 | 
						|
								    # Step 3: Execute Docker build if requested
							 | 
						|
								    if [ "$DOCKER_BUILD" = true ]; then
							 | 
						|
								        safe_execute "Docker build for $BUILD_MODE mode" "execute_docker_build $BUILD_MODE" || exit 4
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    # Print build summary
							 | 
						|
								    log_success "Web build completed successfully!"
							 | 
						|
								    log_info "Build output available in: dist/"
							 | 
						|
								    
							 | 
						|
								    if [ "$DOCKER_BUILD" = true ]; then
							 | 
						|
								        log_info "Docker image available as: timesafari-web:$BUILD_MODE"
							 | 
						|
								    fi
							 | 
						|
								    
							 | 
						|
								    print_footer "Web Build"
							 | 
						|
								    
							 | 
						|
								    # Exit with success
							 | 
						|
								    exit 0
							 | 
						|
								fi 
							 |