Spaces:
Running
Running
File size: 6,129 Bytes
207aa37 5fad218 207aa37 5fad218 207aa37 5fad218 207aa37 5fad218 04706d1 207aa37 5fad218 207aa37 5fad218 207aa37 5fad218 207aa37 5fad218 207aa37 5fad218 207aa37 04706d1 207aa37 04706d1 207aa37 04706d1 207aa37 | 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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | #!/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_PORT="${BACKEND_PORT:-8000}"
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
PYTHON_BIN="${PYTHON_BIN:-}"
BACKEND_PID=""
is_supported_python_version() {
local version="$1"
case "$version" in
3.10|3.11|3.12|3.13)
return 0
;;
*)
return 1
;;
esac
}
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
}
python_bin_works() {
local command_name="$1"
[[ -n "$command_name" ]] && command -v "$command_name" >/dev/null 2>&1
}
python_version_of_bin() {
local command_name="$1"
if python_bin_works "$command_name"; then
"$command_name" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")'
fi
}
venv_python_works() {
local venv_dir="$1"
[[ -x "$venv_dir/bin/python" ]] && "$venv_dir/bin/python" -c 'import sys' >/dev/null 2>&1
}
resolve_python_bin() {
local candidates=()
if [[ -n "$PYTHON_BIN" ]]; then
candidates+=("$PYTHON_BIN")
fi
candidates+=("python3.13" "python3.12" "python3.11" "python3.10" "python3" "python")
local candidate
for candidate in "${candidates[@]}"; do
if python_bin_works "$candidate"; then
local version
version="$(python_version_of_bin "$candidate")"
if is_supported_python_version "$version"; then
echo "$candidate"
return 0
fi
fi
done
return 1
}
resolve_backend_venv() {
if [[ -n "$BACKEND_VENV" ]]; then
echo "$BACKEND_VENV"
return 0
fi
local candidates=(
"$BACKEND_DIR/.venv313"
"$BACKEND_DIR/.venv312"
"$BACKEND_DIR/.venv"
)
local candidate
for candidate in "${candidates[@]}"; do
if venv_python_works "$candidate"; then
local version
version="$(python_version_of_venv "$candidate")"
if is_supported_python_version "$version"; then
echo "$candidate"
return 0
fi
fi
done
if python_bin_works "python3.13"; then
echo "$BACKEND_DIR/.venv313"
return 0
fi
if python_bin_works "python3.12"; then
echo "$BACKEND_DIR/.venv312"
return 0
fi
echo "$BACKEND_DIR/.venv"
}
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() {
BACKEND_VENV="$(resolve_backend_venv)"
PYTHON_BIN="$(resolve_python_bin || true)"
if [[ -z "$PYTHON_BIN" ]]; then
echo "Comando obrigatório não encontrado: python3.13, python3.12, python3.11, python3.10, python3 ou python" >&2
exit 1
fi
local desired_version
desired_version="$(python_version_of_bin "$PYTHON_BIN")"
if [[ -d "$BACKEND_VENV" ]] && venv_python_works "$BACKEND_VENV" && [[ "$(python_version_of_venv "$BACKEND_VENV")" == "$desired_version" ]]; then
echo "Usando ambiente virtual existente em $BACKEND_VENV."
else
if [[ -d "$BACKEND_VENV" ]]; then
local current_version
current_version="$(python_version_of_venv "$BACKEND_VENV")"
echo "A venv em $BACKEND_VENV não está adequada para o ambiente atual." >&2
if [[ -n "$current_version" ]]; then
echo "Ela usa Python $current_version, mas o script vai usar Python $desired_version." >&2
fi
echo "Vou recriar a venv com $PYTHON_BIN (Python $desired_version)." >&2
rm -rf "$BACKEND_VENV"
else
echo "Criando ambiente virtual do backend com $PYTHON_BIN..."
fi
"$PYTHON_BIN" -m venv "$BACKEND_VENV"
fi
if [[ -d "$BACKEND_VENV" ]] && ! venv_python_works "$BACKEND_VENV"; then
local current_version
current_version="$(python_version_of_venv "$BACKEND_VENV")"
echo "A venv em $BACKEND_VENV continua indisponível após a preparação." >&2
echo "Versão detectada: ${current_version:-desconhecida}" >&2
exit 1
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
|