Ctrl K
ComunidadGuías…

scripts/start-frontend.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash
set -euo pipefail

# start-frontend.sh
# Guided script to configure and start the ActaLog frontend (dev or preview)
# Usage: ./scripts/start-frontend.sh

# Script version - increment when making changes
SCRIPT_VERSION="1.3.1"

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WEB_DIR="$ROOT_DIR/web"

# Defaults to avoid 'unbound variable' with 'set -u'
HOST_ARG=""
HTTPS_FLAG=""

echo ""
echo "ActaLog Frontend Starter v${SCRIPT_VERSION}"
echo "========================================="
echo ""

read -r -p "Run in (d)ev or (p)review (production) mode? [d/p]: " MODE
MODE=${MODE:-d}

if [[ "$MODE" != "d" && "$MODE" != "p" ]]; then
  echo "Invalid choice. Use 'd' for dev or 'p' for preview." >&2
  exit 1
fi

read -r -p "Will you access the frontend on this machine's localhost or a domain name? [l=localhost / D=domain]: " HOST_TYPE
HOST_TYPE=${HOST_TYPE:-l}

if [[ "$HOST_TYPE" == "l" || "$HOST_TYPE" == "L" ]]; then
  HOSTNAME="localhost"
  echo "Detected: localhost environment"
  read -r -p "Expose to LAN (so other devices can access)? [y/N]: " EXPOSE
  EXPOSE=${EXPOSE:-N}
  if [[ "$EXPOSE" =~ ^[Yy]$ ]]; then
    HOST_ARG="--host"
  else
    HOST_ARG=""
  fi

  read -r -p "Use HTTPS locally (requires mkcert or custom cert)? [y/N]: " USE_HTTPS
  USE_HTTPS=${USE_HTTPS:-N}
  if [[ "$USE_HTTPS" =~ ^[Yy]$ ]]; then
    HTTPS_FLAG="--https"
    echo "If you want trusted certs, mkcert can create locally-trusted certs (https://github.com/FiloSottile/mkcert)."
    if command -v mkcert >/dev/null 2>&1; then
      read -r -p "mkcert is installed — generate certs for '$HOSTNAME' now? [y/N]: " MKCERT_YES
      MKCERT_YES=${MKCERT_YES:-N}
      if [[ "$MKCERT_YES" =~ ^[Yy]$ ]]; then
        CERT_DIR="$WEB_DIR/certs"
        mkdir -p "$CERT_DIR"
        echo "Running: mkcert -install (may prompt for permission)..."
        mkcert -install || true
        CERT_PEM="$CERT_DIR/$HOSTNAME.pem"
        CERT_KEY="$CERT_DIR/$HOSTNAME-key.pem"
        echo "Generating certs for: $HOSTNAME (and localhost/127.0.0.1)..."
        mkcert -cert-file "$CERT_PEM" -key-file "$CERT_KEY" "$HOSTNAME" localhost 127.0.0.1
        echo "Created cert files:"
        echo "  $CERT_PEM"
        echo "  $CERT_KEY"
        echo ""
        echo "Next steps (one-time):"
        echo "- Keep these files under 'web/certs' (already created)."
        echo "- Update your 'web/vite.config.js' to point Vite's server.https to these files (example below)."
        echo ""
        echo "Paste this snippet into your 'web/vite.config.js' (add 'import fs from \"fs\"'):"
        echo ""
        cat <<EOF
server: {
  host: '$HOSTNAME',
  https: {
    key: fs.readFileSync('certs/$HOSTNAME-key.pem'),
    cert: fs.readFileSync('certs/$HOSTNAME.pem')
  }
}
EOF
        echo ""
        echo "Or run preview with flags (does not require editing config):"
        echo "  npm run preview -- --https --host $HOSTNAME"
      else
        echo "Skipping mkcert generation — you'll need to provide certs and update Vite config if you want HTTPS."
      fi
    else
      echo "mkcert not found. Install it from https://github.com/FiloSottile/mkcert and re-run this script to auto-generate certs."
      echo "You can still run preview with '--https' if you provide certs in Vite config."
    fi
  else
    HTTPS_FLAG=""
  fi

else
  read -r -p "Enter the domain you'll use (e.g. actalog.example.com): " HOSTNAME
  if [[ -z "$HOSTNAME" ]]; then
    echo "A domain name is required for domain mode." >&2
    exit 1
  fi
  echo "Domain mode: $HOSTNAME"

  # Verify DNS resolution
  echo "\nVerifying DNS configuration for $HOSTNAME..."
  RESOLVED_IP=""
  if command -v dig >/dev/null 2>&1; then
    # Use dig if available (more reliable)
    RESOLVED_IP=$(dig +short "$HOSTNAME" A | head -n 1)
  elif command -v nslookup >/dev/null 2>&1; then
    # Fall back to nslookup
    RESOLVED_IP=$(nslookup "$HOSTNAME" 2>/dev/null | grep -A 1 "Name:" | tail -n 1 | awk '{print $2}')
  elif command -v host >/dev/null 2>&1; then
    # Fall back to host command
    RESOLVED_IP=$(host "$HOSTNAME" 2>/dev/null | grep "has address" | head -n 1 | awk '{print $NF}')
  fi

  if [[ -n "$RESOLVED_IP" ]]; then
    echo "✓ DNS resolved: $HOSTNAME → $RESOLVED_IP"

    # Get local machine's IP addresses
    LOCAL_IPS=""
    if command -v hostname >/dev/null 2>&1; then
      LOCAL_IPS=$(hostname -I 2>/dev/null || hostname -i 2>/dev/null || echo "")
    fi

    # Check if resolved IP matches any local IP
    IP_MATCHES=false
    if [[ -n "$LOCAL_IPS" ]]; then
      for LOCAL_IP in $LOCAL_IPS; do
        if [[ "$RESOLVED_IP" == "$LOCAL_IP" ]]; then
          IP_MATCHES=true
          echo "✓ DNS points to this machine ($LOCAL_IP)"
          break
        fi
      done

      if [[ "$IP_MATCHES" == false ]]; then
        echo "⚠ WARNING: DNS does not point to this machine!"
        echo "  Resolved IP: $RESOLVED_IP"
        echo "  Local IPs:   $LOCAL_IPS"
        echo "\nThis may cause issues unless:"
        echo "  - You're behind a NAT/router doing port forwarding"
        echo "  - You're testing with /etc/hosts override"
        echo "  - The domain points to a load balancer that forwards here"
      fi
    else
      echo "Could not determine local IP addresses for comparison."
    fi

    read -r -p "\nIs the resolved IP ($RESOLVED_IP) correct? [Y/n]: " IP_CORRECT
    IP_CORRECT=${IP_CORRECT:-Y}
    if [[ ! "$IP_CORRECT" =~ ^[Yy]$ ]]; then
      echo "\n✗ DNS configuration issue detected!"
      echo "Please fix your DNS records before continuing:"
      echo "  1. Add/update an A record for '$HOSTNAME' pointing to your server's public IP"
      echo "  2. Wait for DNS propagation (can take 5 minutes to 48 hours)"
      echo "  3. Verify with: dig $HOSTNAME"
      read -r -p "\nContinue anyway? [y/N]: " CONTINUE_ANYWAY
      CONTINUE_ANYWAY=${CONTINUE_ANYWAY:-N}
      if [[ ! "$CONTINUE_ANYWAY" =~ ^[Yy]$ ]]; then
        echo "Exiting. Fix DNS configuration and re-run this script."
        exit 1
      fi
    fi
  else
    echo "✗ WARNING: Could not resolve DNS for '$HOSTNAME'"
    echo "This domain does not appear to have a valid A record."
    echo "\nPossible issues:"
    echo "  - Domain/subdomain does not exist"
    echo "  - DNS not yet propagated"
    echo "  - DNS server issue"
    echo "\nTo fix:"
    echo "  1. Add an A record for '$HOSTNAME' in your DNS provider"
    echo "  2. Point it to this server's public IP address"
    echo "  3. Wait for DNS propagation (typically 5-30 minutes)"
    echo "  4. Verify with: dig $HOSTNAME"

    read -r -p "\nContinue anyway (for local testing with /etc/hosts)? [y/N]: " CONTINUE_ANYWAY
    CONTINUE_ANYWAY=${CONTINUE_ANYWAY:-N}
    if [[ ! "$CONTINUE_ANYWAY" =~ ^[Yy]$ ]]; then
      echo "Exiting. Configure DNS and re-run this script."
      exit 1
    fi
  fi

  # Ask if using a reverse proxy (Caddy)
  read -r -p "Will you use a reverse proxy like Caddy to handle HTTPS? [Y/n]: " USE_PROXY
  USE_PROXY=${USE_PROXY:-Y}

  if [[ "$USE_PROXY" =~ ^[Yy]$ ]]; then
    echo "Reverse proxy mode: The frontend will run HTTP-only (no HTTPS flag needed)."
    echo "Your reverse proxy (e.g., Caddy) will handle HTTPS and forward requests to the frontend."
    echo "\nMake sure:"
    echo "  - DNS A/AAAA record points to this machine"
    echo "  - Reverse proxy is configured to proxy to localhost:3000 (or your configured port)"
    echo "  - Reverse proxy handles SSL/TLS certificates (Caddy does this automatically via Let's Encrypt)"
    HTTPS_FLAG=""
  else
    read -r -p "Will you use HTTPS directly on the frontend? [Y/n]: " USE_HTTPS
    USE_HTTPS=${USE_HTTPS:-Y}
    if [[ "$USE_HTTPS" =~ ^[Yy]$ ]]; then
      HTTPS_FLAG="--https"
      echo "Ensure DNS A/AAAA record points to this machine and that you have certs available (mkcert for local dev or real certs in production)."
    else
      HTTPS_FLAG=""
    fi
  fi

  # Give guidance about hosts file if it's local testing with domain
  echo "\nIf you're testing a domain locally, add an entry to /etc/hosts (or C:\\Windows\\System32\\drivers\\etc\\hosts on Windows):"
  echo "  <your-machine-ip>  $HOSTNAME"
fi

echo "\nSummary:"
echo " Mode:       $([[ $MODE == 'd' ]] && echo 'dev' || echo 'preview')"
echo " Hostname:   $HOSTNAME"
echo " HTTPS flag: ${HTTPS_FLAG:-none}"

# Check if port 3000 is already in use
PORT=3000
PORT_IN_USE=false
PROCESS_INFO=""

if command -v lsof >/dev/null 2>&1; then
  PROCESS_INFO=$(lsof -ti:$PORT 2>/dev/null | head -n 1 || true)
elif command -v ss >/dev/null 2>&1; then
  PROCESS_INFO=$(ss -tlnp 2>/dev/null | grep ":$PORT " | head -n 1 || true)
elif command -v netstat >/dev/null 2>&1; then
  PROCESS_INFO=$(netstat -tlnp 2>/dev/null | grep ":$PORT " | head -n 1 || true)
fi

if [[ -n "$PROCESS_INFO" ]]; then
  PORT_IN_USE=true
  echo "\n⚠ WARNING: Port $PORT is already in use!"

  # Try to get more detailed process information
  if command -v lsof >/dev/null 2>&1; then
    PID=$(lsof -ti:$PORT 2>/dev/null | head -n 1 || true)
    if [[ -n "$PID" ]]; then
      PROC_NAME=$(ps -p "$PID" -o comm= 2>/dev/null || echo "unknown")
      PROC_CMD=$(ps -p "$PID" -o args= 2>/dev/null || echo "unknown")
      echo "  Process ID:   $PID"
      echo "  Process name: $PROC_NAME"
      echo "  Command:      $PROC_CMD"
    else
      echo "  $PROCESS_INFO"
    fi
  else
    echo "  $PROCESS_INFO"
  fi

  echo "\nOptions:"
  echo "  1) Stop the existing process and start ActaLog on port $PORT"
  echo "  2) Start ActaLog on a different port"
  echo "  3) Cancel and exit"

  read -r -p "\nChoose an option [1/2/3]: " PORT_CHOICE
  PORT_CHOICE=${PORT_CHOICE:-3}

  case "$PORT_CHOICE" in
    1)
      echo "\nAttempting to stop process on port $PORT..."
      if command -v lsof >/dev/null 2>&1; then
        PID=$(lsof -ti:$PORT 2>/dev/null | head -n 1 || true)
        if [[ -n "$PID" ]]; then
          echo "Killing process $PID..."
          kill "$PID" 2>/dev/null || kill -9 "$PID" 2>/dev/null || {
            echo "✗ Failed to kill process. You may need sudo privileges."
            read -r -p "Try with sudo? [y/N]: " USE_SUDO
            USE_SUDO=${USE_SUDO:-N}
            if [[ "$USE_SUDO" =~ ^[Yy]$ ]]; then
              sudo kill "$PID" 2>/dev/null || sudo kill -9 "$PID" 2>/dev/null || {
                echo "✗ Failed to kill process even with sudo. Exiting."
                exit 1
              }
            else
              echo "Exiting."
              exit 1
            fi
          }
          # Wait for port to be released
          sleep 2
          echo "✓ Process stopped. Proceeding with port $PORT..."
        fi
      else
        echo "✗ Cannot automatically kill process (lsof not available)."
        echo "Please manually stop the process using port $PORT and re-run this script."
        exit 1
      fi
      ;;
    2)
      echo "\nFinding an available port..."
      # Find next available port starting from 3001
      for TEST_PORT in {3001..3010}; do
        if ! lsof -ti:$TEST_PORT >/dev/null 2>&1 && ! ss -tln 2>/dev/null | grep -q ":$TEST_PORT "; then
          PORT=$TEST_PORT
          echo "✓ Found available port: $PORT"
          break
        fi
      done

      if [[ "$PORT" == "3000" ]]; then
        echo "✗ Could not find an available port in range 3001-3010"
        exit 1
      fi

      echo "\n📌 IMPORTANT: ActaLog will start on port $PORT"
      echo "   Access it at: http://$HOSTNAME:$PORT"
      if [[ "$USE_PROXY" =~ ^[Yy]$ ]]; then
        echo "\n   ⚠ Remember to update your reverse proxy configuration!"
        echo "   Change 'reverse_proxy localhost:3000' to 'reverse_proxy localhost:$PORT'"
        echo "   in your Caddyfile or nginx config."
      fi
      ;;
    3)
      echo "Exiting."
      exit 0
      ;;
    *)
      echo "Invalid choice. Exiting."
      exit 1
      ;;
  esac
fi

cd "$WEB_DIR"

# Show final configuration
echo ""
echo "========================================="
echo "Starting ActaLog Frontend v${SCRIPT_VERSION}"
echo "========================================="
echo " Port:     $PORT"
echo " Mode:     $([[ $MODE == 'd' ]] && echo 'Development' || echo 'Preview (Production-like)')"
echo " Hostname: $HOSTNAME"
if [[ "$PORT" != "3000" ]]; then
  echo ""
  echo "⚠ Using non-standard port: $PORT"
  echo "   Access URL: http://$HOSTNAME:$PORT"
fi
echo "========================================="
echo ""

# Export environment variables for Vite configuration
export VITE_DEV_HOST="$HOSTNAME"
export VITE_DEV_PORT="$PORT"

# Set HTTPS flag for Vite
if [[ -n "$HTTPS_FLAG" ]]; then
  export VITE_USE_HTTPS="true"
else
  export VITE_USE_HTTPS="false"
fi

# Determine bind address for Vite server
# When using reverse proxy, bind to 0.0.0.0 (all interfaces), not the domain name
if [[ "$HOST_TYPE" == "l" || "$HOST_TYPE" == "L" ]]; then
  BIND_HOST="$HOSTNAME"  # localhost or other host from config
else
  # Domain mode with reverse proxy: bind to 0.0.0.0
  if [[ "${USE_PROXY:-N}" =~ ^[Yy]$ ]]; then
    BIND_HOST="0.0.0.0"
  else
    BIND_HOST="$HOSTNAME"
  fi
fi

# Construct deployment URL for PWA manifest and build configuration
if [[ "$HOST_TYPE" == "l" || "$HOST_TYPE" == "L" ]]; then
  # Localhost mode - always include port
  if [[ -n "$HTTPS_FLAG" ]]; then
    export VITE_DEPLOYMENT_URL="https://$HOSTNAME:$PORT"
  else
    export VITE_DEPLOYMENT_URL="http://$HOSTNAME:$PORT"
  fi
else
  # Domain mode
  if [[ "${USE_PROXY:-N}" =~ ^[Yy]$ ]]; then
    # Using reverse proxy - don't include port in public URL
    # (proxy listens on 80/443 and forwards to localhost:$PORT)
    export VITE_DEPLOYMENT_URL="https://$HOSTNAME"
  else
    # Direct access - include port in URL
    if [[ -n "$HTTPS_FLAG" ]]; then
      export VITE_DEPLOYMENT_URL="https://$HOSTNAME:$PORT"
    else
      export VITE_DEPLOYMENT_URL="http://$HOSTNAME:$PORT"
    fi
  fi
fi

if [[ "$MODE" == "d" ]]; then
  # Use npm script (vite). Provide host/https flags directly to the vite CLI.
  # `npm run dev -- --host` passes flags through to vite.
  if [[ -n "$HOST_ARG" ]]; then
    echo "Running: npm run dev -- $HOST_ARG --port $PORT $HTTPS_FLAG"
    exec npm run dev -- $HOST_ARG --port $PORT $HTTPS_FLAG
  else
    echo "Running: npm run dev -- --port $PORT $HTTPS_FLAG"
    exec npm run dev -- --port $PORT $HTTPS_FLAG
  fi
else
  echo ""
  echo "Building and starting preview (production-like) server on port $PORT..."
  # Note: vite preview does NOT accept --https as a CLI flag
  # HTTPS is controlled via vite.config.js server.https setting
  # If certs exist in web/certs/, the preview server will use HTTPS automatically
  if [[ -n "$HTTPS_FLAG" ]]; then
    echo "Note: HTTPS for preview mode is configured via vite.config.js (not CLI flags)"
    echo "Ensure cert files exist in web/certs/ for HTTPS support"
    echo "Running: VITE_DEV_HOST=$HOSTNAME VITE_DEV_PORT=$PORT VITE_USE_HTTPS=$VITE_USE_HTTPS VITE_DEPLOYMENT_URL=$VITE_DEPLOYMENT_URL npm run build && npm run preview -- --host $BIND_HOST --port $PORT"
  else
    echo "Running: VITE_DEV_HOST=$HOSTNAME VITE_DEV_PORT=$PORT VITE_USE_HTTPS=$VITE_USE_HTTPS VITE_DEPLOYMENT_URL=$VITE_DEPLOYMENT_URL npm run build && npm run preview -- --host $BIND_HOST --port $PORT"
  fi
  VITE_DEV_HOST="$HOSTNAME" VITE_DEV_PORT="$PORT" VITE_USE_HTTPS="$VITE_USE_HTTPS" VITE_DEPLOYMENT_URL="$VITE_DEPLOYMENT_URL" npm run build
  exec npm run preview -- --host $BIND_HOST --port $PORT
fi