File size: 3,638 Bytes
7fabf33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env bash

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$ROOT_DIR/backend"
FRONTEND_DIR="$ROOT_DIR/frontend"
BACKEND_VENV="${BACKEND_VENV:-$BACKEND_DIR/.venv313}"
BACKEND_PORT="${BACKEND_PORT:-8000}"
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
PYTHON_BIN="${PYTHON_BIN:-python3.13}"
BACKEND_PID=""

cleanup() {
  if [[ -n "$BACKEND_PID" ]] && kill -0 "$BACKEND_PID" >/dev/null 2>&1; then
    echo ""
    echo "Encerrando backend..."
    kill "$BACKEND_PID" >/dev/null 2>&1 || true
    wait "$BACKEND_PID" 2>/dev/null || true
  fi
}

trap cleanup EXIT INT TERM

require_command() {
  local command_name="$1"
  if ! command -v "$command_name" >/dev/null 2>&1; then
    echo "Comando obrigatório não encontrado: $command_name" >&2
    exit 1
  fi
}

port_in_use() {
  local port="$1"
  lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1
}

pick_available_port() {
  local port="$1"
  while port_in_use "$port"; do
    port=$((port + 1))
  done
  echo "$port"
}

python_version_of_venv() {
  local venv_dir="$1"
  if [[ -x "$venv_dir/bin/python" ]]; then
    "$venv_dir/bin/python" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")'
  fi
}

ensure_backend_env() {
  require_command "$PYTHON_BIN"

  local desired_version
  desired_version="$("$PYTHON_BIN" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"

  if [[ ! -d "$BACKEND_VENV" ]]; then
    echo "Criando ambiente virtual do backend com $PYTHON_BIN..."
    "$PYTHON_BIN" -m venv "$BACKEND_VENV"
  else
    local current_version
    current_version="$(python_version_of_venv "$BACKEND_VENV")"
    if [[ "$current_version" != "$desired_version" ]]; then
      echo "A venv em $BACKEND_VENV usa Python $current_version, mas o script espera Python $desired_version." >&2
      echo "Apague essa venv ou rode com BACKEND_VENV apontando para outra pasta." >&2
      echo "Sugestão segura:" >&2
      echo "  mv \"$BACKEND_VENV\" \"${BACKEND_VENV}.old\"" >&2
      echo "Depois rode novamente ./dev.sh" >&2
      exit 1
    fi
  fi

  echo "Instalando/verificando dependências do backend..."
  # shellcheck disable=SC1091
  source "$BACKEND_VENV/bin/activate"
  pip install -r "$BACKEND_DIR/requirements.txt" >/dev/null
}

ensure_frontend_env() {
  require_command npm

  if [[ ! -d "$FRONTEND_DIR/node_modules" ]] || [[ ! -x "$FRONTEND_DIR/node_modules/.bin/vite" ]]; then
    echo "Instalando dependências do frontend..."
    (cd "$FRONTEND_DIR" && npm install)
  fi
}

prepare_ports() {
  if port_in_use "$BACKEND_PORT"; then
    local requested_port="$BACKEND_PORT"
    BACKEND_PORT="$(pick_available_port "$BACKEND_PORT")"
    echo "Porta $requested_port já está em uso no backend. Usando $BACKEND_PORT."
  fi

  if port_in_use "$FRONTEND_PORT"; then
    local requested_port="$FRONTEND_PORT"
    FRONTEND_PORT="$(pick_available_port "$FRONTEND_PORT")"
    echo "Porta $requested_port já está em uso no frontend. Usando $FRONTEND_PORT."
  fi
}

start_backend() {
  echo "Subindo backend em http://127.0.0.1:$BACKEND_PORT ..."
  (
    cd "$BACKEND_DIR"
    # shellcheck disable=SC1091
    source "$BACKEND_VENV/bin/activate"
    uvicorn app.main:app --reload --host 127.0.0.1 --port "$BACKEND_PORT"
  ) &
  BACKEND_PID=$!
}

start_frontend() {
  echo "Subindo frontend em http://127.0.0.1:$FRONTEND_PORT ..."
  cd "$FRONTEND_DIR"
  VITE_API_BASE_URL="http://127.0.0.1:$BACKEND_PORT" npm run dev -- --host 127.0.0.1 --port "$FRONTEND_PORT"
}

echo "Preparando ambiente de desenvolvimento..."
ensure_backend_env
ensure_frontend_env
prepare_ports
start_backend
start_frontend