#!/bin/bash # SaveInMed Development Startup Script # Permite iniciar um ou mais serviços do projeto # Cores para output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # No Color # Diretório raiz do projeto PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Função para exibir o banner show_banner() { echo -e "${CYAN}" echo "╔══════════════════════════════════════════════════╗" echo "║ ║" echo "║ ███████ █████ ██ ██ ███████ ██ ███ ██ ║" echo "║ ██ ██ ██ ██ ██ ██ ██ ████ ██ ║" echo "║ ███████ ███████ ██ ██ █████ ██ ██ ██ ██ ║" echo "║ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ║" echo "║ ███████ ██ ██ ████ ███████ ██ ██ ████ ║" echo "║ ║" echo "║ ███ ███ ███████ ██████ ║" echo "║ ████ ████ ██ ██ ██ ║" echo "║ ██ ████ ██ █████ ██ ██ ║" echo "║ ██ ██ ██ ██ ██ ██ ║" echo "║ ██ ██ ███████ ██████ ║" echo "║ ║" echo "║ Development Startup Script ║" echo "║ ║" echo "╚══════════════════════════════════════════════════╝" echo -e "${NC}" } # Função para verificar dependências check_dependency() { local cmd=$1 local name=$2 if command -v "$cmd" &> /dev/null; then echo -e " ${GREEN}✓${NC} $name" return 0 else echo -e " ${RED}✗${NC} $name (não instalado)" return 1 fi } # Função para instalar Go install_go() { echo -e "${YELLOW}📦 Instalando Go...${NC}" curl -fsSL https://go.dev/dl/go1.24.3.linux-amd64.tar.gz -o /tmp/go.tar.gz sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf /tmp/go.tar.gz export PATH=$PATH:/usr/local/go/bin echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrc rm /tmp/go.tar.gz echo -e "${GREEN}✓ Go instalado com sucesso${NC}" } # Função para instalar Node.js install_node() { echo -e "${YELLOW}📦 Instalando Node.js...${NC}" curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs echo -e "${GREEN}✓ Node.js instalado com sucesso${NC}" } # Função para instalar pnpm install_pnpm() { echo -e "${YELLOW}📦 Instalando pnpm...${NC}" npm install -g pnpm echo -e "${GREEN}✓ pnpm instalado com sucesso${NC}" } # Função para instalar Deno install_deno() { echo -e "${YELLOW}📦 Instalando Deno...${NC}" curl -fsSL https://deno.land/install.sh | sh export DENO_INSTALL="$HOME/.deno" export PATH="$DENO_INSTALL/bin:$PATH" echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.zshrc echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.zshrc echo -e "${GREEN}✓ Deno instalado com sucesso${NC}" } # Função para instalar tmux install_tmux() { echo -e "${YELLOW}📦 Instalando tmux...${NC}" sudo apt-get update && sudo apt-get install -y tmux echo -e "${GREEN}✓ tmux instalado com sucesso${NC}" } # Função para verificar e instalar dependência ensure_dependency() { local cmd=$1 local name=$2 local install_func=$3 if ! command -v "$cmd" &> /dev/null; then echo -e "${RED}✗ $name não está instalado${NC}" read -p "Deseja instalar $name agora? (s/n): " install_choice if [[ "$install_choice" =~ ^[Ss]$ ]]; then $install_func return 0 else echo -e "${RED}Não é possível continuar sem $name${NC}" return 1 fi fi return 0 } # Função para iniciar o Backend Go start_backend() { echo -e "\n${BLUE}🚀 Iniciando Backend Go...${NC}" # Verificar/instalar Go ensure_dependency "go" "Go" "install_go" || return 1 cd "$PROJECT_ROOT/backend" # Carregar variáveis de ambiente se existir .env if [ -f ".env" ]; then echo -e "${GREEN} ✓ Carregando variáveis de .env${NC}" set -a source .env set +a else echo -e "${YELLOW} ⚠ Arquivo .env não encontrado, usando valores padrão${NC}" fi # Baixar dependências se necessário if [ ! -f "go.sum" ]; then echo -e "${YELLOW} 📦 Baixando dependências Go...${NC}" go mod download fi echo -e "${GREEN} ▶ Executando: go run ./cmd/api${NC}" echo -e "${CYAN} 📍 API disponível em: http://localhost:${PORT:-8214}${NC}" echo -e "${CYAN} 📚 Swagger UI: http://localhost:${PORT:-8214}/swagger/index.html${NC}\n" go run ./cmd/api } # Função para iniciar o Backoffice NestJS start_backoffice() { echo -e "\n${PURPLE}🚀 Iniciando Backoffice NestJS...${NC}" # Verificar/instalar Node.js ensure_dependency "node" "Node.js" "install_node" || return 1 # Verificar/instalar pnpm if ! command -v pnpm &> /dev/null; then read -p "pnpm não encontrado. Deseja instalar? (s/n): " install_choice if [[ "$install_choice" =~ ^[Ss]$ ]]; then install_pnpm fi fi cd "$PROJECT_ROOT/backoffice" # Determinar gerenciador de pacotes (pnpm ou npm) if command -v pnpm &> /dev/null; then PKG_MANAGER="pnpm" else PKG_MANAGER="npm" echo -e "${YELLOW} ⚠ pnpm não encontrado, usando npm${NC}" fi # Instalar dependências se necessário if [ ! -d "node_modules" ]; then echo -e "${YELLOW} 📦 Instalando dependências...${NC}" $PKG_MANAGER install fi # Gerar Prisma client if [ -f "prisma/schema.prisma" ]; then echo -e "${YELLOW} 🔧 Gerando Prisma client...${NC}" $PKG_MANAGER run prisma:generate 2>/dev/null || npx prisma generate fi echo -e "${GREEN} ▶ Executando: $PKG_MANAGER run start:dev${NC}" echo -e "${CYAN} 📍 Backoffice disponível em: http://localhost:3000${NC}" echo -e "${CYAN} 📚 Swagger: http://localhost:3000/docs${NC}\n" $PKG_MANAGER run start:dev } # Função para iniciar o Marketplace React start_marketplace() { echo -e "\n${BLUE}🚀 Iniciando Marketplace React...${NC}" # Verificar/instalar Node.js ensure_dependency "node" "Node.js" "install_node" || return 1 cd "$PROJECT_ROOT/marketplace" # Instalar dependências se necessário if [ ! -d "node_modules" ]; then echo -e "${YELLOW} 📦 Instalando dependências...${NC}" npm install fi echo -e "${GREEN} ▶ Executando: npm run dev${NC}" echo -e "${CYAN} 📍 Marketplace disponível em: http://localhost:5173${NC}\n" npm run dev } # Função para iniciar o Website Fresh/Deno start_website() { echo -e "\n${GREEN}🚀 Iniciando Website (Fresh/Deno)...${NC}" # Verificar/instalar Deno ensure_dependency "deno" "Deno" "install_deno" || return 1 cd "$PROJECT_ROOT/website" echo -e "${GREEN} ▶ Executando: deno task dev${NC}" echo -e "${CYAN} 📍 Website disponível em: http://localhost:8000${NC}\n" deno task dev } # Função para resetar e popular o banco de dados reset_db() { echo -e "\n${RED}⚠️ ATENÇÃO: Isso irá apagar todo o banco de dados e recriá-lo!${NC}" echo -e "${YELLOW} Isso inclui: companies, users, products, orders, etc.${NC}" # Se não for chamado via flag (automático), pede confirmação if [ "$1" != "--force" ]; then read -p " Deseja continuar? (s/n): " confirm if [[ ! "$confirm" =~ ^[Ss]$ ]]; then echo -e "${YELLOW}Operação cancelada.${NC}" return 0 fi fi echo -e "\n${BLUE}🚜 Iniciando Seeder API...${NC}" # Verificar/instalar Go ensure_dependency "go" "Go" "install_go" || return 1 cd "$PROJECT_ROOT/seeder-api" # Carregar variáveis de ambiente if [ -f "../backend/.env" ]; then set -a source ../backend/.env set +a fi # Usar porta diferente para evitar conflito se o seeder tiver padrão diferente # O seeder usa PORT env var. Vamos definir uma temporária se não estiver definida export PORT=${PORT:-8216} # Iniciar seeder em background echo -e "${YELLOW} ⏳ Aguardando Seeder API iniciar na porta $PORT...${NC}" go run main.go & SEEDER_PID=$! # Aguardar serviço estar pronto max_retries=30 count=0 while ! curl -s "http://localhost:$PORT/swagger.json" > /dev/null; do sleep 1 count=$((count+1)) if [ $count -ge $max_retries ]; then echo -e "${RED}❌ Timeout aguardando Seeder API${NC}" kill $SEEDER_PID 2>/dev/null return 1 fi echo -n "." done echo "" echo -e "${GREEN} ✓ Seeder API online!${NC}" echo -e "${YELLOW} 🌱 Executando seed (mode=lean)...${NC}" # Executar seed HTTP_CODE=$(curl -s -o /tmp/seed_output.json -w "%{http_code}" -X POST "http://localhost:$PORT/seed?mode=lean") if [ "$HTTP_CODE" == "200" ]; then echo -e "${GREEN} ✅ Banco de dados resetado e populado com sucesso!${NC}" cat /tmp/seed_output.json echo "" else echo -e "${RED} ❌ Falha ao rodar seed. Código HTTP: $HTTP_CODE${NC}" cat /tmp/seed_output.json echo "" fi # Matar seeder echo -e "${BLUE} 🛑 Parando Seeder API...${NC}" kill $SEEDER_PID 2>/dev/null wait $SEEDER_PID 2>/dev/null echo -e "${GREEN}✨ Concluído!${NC}\n" } # Função para rodar testes e exibir cobertura run_tests() { echo -e "\n${BLUE}🧪 Executando Testes...${NC}\n" # Backend Go Tests echo -e "${CYAN}━━━ Backend Go ━━━${NC}" cd "$PROJECT_ROOT/backend" if [ -f ".env" ]; then set -a source .env set +a fi echo -e "${YELLOW} ⏳ Executando go test com cobertura...${NC}" go test -coverprofile=coverage.out ./... 2>&1 BACKEND_EXIT=$? if [ $BACKEND_EXIT -eq 0 ]; then echo -e "${GREEN} ✓ Testes do backend passaram!${NC}" echo -e "${CYAN} 📊 Cobertura:${NC}" go tool cover -func=coverage.out | tail -1 echo -e "\n${YELLOW} 💡 Para ver cobertura detalhada: cd backend && go tool cover -html=coverage.out${NC}" else echo -e "${RED} ✗ Alguns testes falharam${NC}" fi echo "" # Marketplace Tests echo -e "${CYAN}━━━ Marketplace React ━━━${NC}" cd "$PROJECT_ROOT/marketplace" if [ -d "node_modules" ]; then echo -e "${YELLOW} ⏳ Executando vitest...${NC}" npm run test -- --coverage --run 2>&1 MARKET_EXIT=$? if [ $MARKET_EXIT -eq 0 ]; then echo -e "${GREEN} ✓ Testes do marketplace passaram!${NC}" else echo -e "${RED} ✗ Alguns testes falharam${NC}" fi else echo -e "${YELLOW} ⚠ node_modules não encontrado. Execute: npm install${NC}" fi echo -e "\n${GREEN}✨ Testes concluídos!${NC}\n" } # Função para verificar build de todos os projetos run_build_check() { echo -e "\n${BLUE}🔨 Verificando Build...${NC}\n" ALL_OK=true # Backend Go Build echo -e "${CYAN}━━━ Backend Go ━━━${NC}" cd "$PROJECT_ROOT/backend" echo -e "${YELLOW} ⏳ go build ./...${NC}" if go build ./... 2>&1; then echo -e "${GREEN} ✓ Build OK${NC}" else echo -e "${RED} ✗ Build falhou${NC}" ALL_OK=false fi echo "" # Marketplace Build echo -e "${CYAN}━━━ Marketplace React ━━━${NC}" cd "$PROJECT_ROOT/marketplace" if [ -d "node_modules" ]; then echo -e "${YELLOW} ⏳ npm run build${NC}" if npm run build 2>&1; then echo -e "${GREEN} ✓ Build OK${NC}" else echo -e "${RED} ✗ Build falhou${NC}" ALL_OK=false fi else echo -e "${YELLOW} ⚠ node_modules não encontrado. Execute: npm install${NC}" fi echo "" # Backoffice Build (if exists) if [ -d "$PROJECT_ROOT/backoffice" ]; then echo -e "${CYAN}━━━ Backoffice NestJS ━━━${NC}" cd "$PROJECT_ROOT/backoffice" if [ -d "node_modules" ]; then PKG_MANAGER="npm" command -v pnpm &>/dev/null && PKG_MANAGER="pnpm" echo -e "${YELLOW} ⏳ $PKG_MANAGER run build${NC}" if $PKG_MANAGER run build 2>&1; then echo -e "${GREEN} ✓ Build OK${NC}" else echo -e "${RED} ✗ Build falhou${NC}" ALL_OK=false fi else echo -e "${YELLOW} ⚠ node_modules não encontrado${NC}" fi echo "" fi if [ "$ALL_OK" = true ]; then echo -e "${GREEN}✨ Todos os builds passaram!${NC}\n" else echo -e "${RED}❌ Alguns builds falharam. Verifique os erros acima.${NC}\n" fi } # Função para exibir o menu show_menu() { echo -e "\n${YELLOW}Selecione o serviço para iniciar:${NC}\n" echo -e " ${BLUE}1)${NC} Backend Go ${CYAN}(porta 8214)${NC}" echo -e " ${BLUE}2)${NC} Backoffice NestJS ${CYAN}(porta 3000)${NC}" echo -e " ${BLUE}3)${NC} Marketplace React ${CYAN}(porta 5173)${NC}" echo -e " ${BLUE}4)${NC} Website Fresh/Deno ${CYAN}(porta 8000)${NC}" echo -e "" echo -e " ${GREEN}5)${NC} Iniciar Todos os Serviços" echo -e "" echo -e " ${PURPLE}6)${NC} Resetar DB (Seed) ${RED}(Destrutivo)${NC}" echo -e " ${YELLOW}7)${NC} Rodar Testes ${CYAN}(com cobertura)${NC}" echo -e " ${YELLOW}8)${NC} Verificar Build ${CYAN}(frontend + backend)${NC}" echo -e "" echo -e " ${RED}0)${NC} Sair" echo -e "" } # Função para iniciar todos os serviços em terminais separados start_all_services() { echo -e "\n${GREEN}🚀 Iniciando todos os serviços...${NC}\n" # Verificar/instalar tmux ensure_dependency "tmux" "tmux" "install_tmux" || return 1 # Matar sessão anterior se existir tmux kill-session -t saveinmed 2>/dev/null || true tmux new-session -d -s saveinmed -n backend "cd $PROJECT_ROOT && ./start.sh --backend" tmux new-window -t saveinmed -n backoffice "cd $PROJECT_ROOT && ./start.sh --backoffice" tmux new-window -t saveinmed -n marketplace "cd $PROJECT_ROOT && ./start.sh --marketplace" tmux new-window -t saveinmed -n website "cd $PROJECT_ROOT && ./start.sh --website" echo -e "${GREEN}✓ Serviços iniciados em sessão tmux 'saveinmed'${NC}" echo -e "${CYAN} Use 'tmux attach -t saveinmed' para acessar${NC}" echo -e "${CYAN} Use Ctrl+B + número para trocar de janela${NC}\n" tmux attach -t saveinmed } # Processar argumentos de linha de comando if [ $# -gt 0 ]; then case "$1" in --backend|-b|1) start_backend exit 0 ;; --backoffice|-o|2) start_backoffice exit 0 ;; --marketplace|-m|3) start_marketplace exit 0 ;; --website|-w|4) start_website exit 0 ;; --seed|-s|6) reset_db "--force" exit 0 ;; --all|-a|5) show_banner start_all_services exit 0 ;; --test|-t|7) show_banner run_tests exit 0 ;; --build|-B|8) show_banner run_build_check exit 0 ;; --help|-h) show_banner echo "Uso: $0 [OPÇÃO]" echo "" echo "Opções:" echo " --backend, -b, 1 Iniciar Backend Go (porta 8214)" echo " --backoffice, -o, 2 Iniciar Backoffice NestJS (porta 3000)" echo " --marketplace, -m, 3 Iniciar Marketplace React (porta 5173)" echo " --website, -w, 4 Iniciar Website Deno (porta 8000)" echo " --seed, -s, 6 Resetar DB e rodar Seed (com --force)" echo " --all, -a, 5 Iniciar todos os serviços" echo " --test, -t, 7 Rodar testes com cobertura" echo " --build, -B, 8 Verificar build de todos os projetos" echo " --help, -h Mostrar esta ajuda" echo "" exit 0 ;; *) echo -e "${RED}Opção inválida: $1${NC}" echo "Use --help para ver as opções disponíveis" exit 1 ;; esac fi # Menu interativo show_banner echo -e "${YELLOW}Verificando dependências...${NC}" echo "" check_dependency "go" "Go" check_dependency "node" "Node.js" check_dependency "npm" "npm" check_dependency "pnpm" "pnpm (opcional, usa npm como fallback)" check_dependency "deno" "Deno" check_dependency "tmux" "tmux (para iniciar todos)" echo "" while true; do show_menu read -p "Opção: " choice case $choice in 1) start_backend break ;; 2) start_backoffice break ;; 3) start_marketplace break ;; 4) start_website break ;; 6) reset_db break ;; 7) run_tests break ;; 8) run_build_check break ;; 5) start_all_services break ;; 0) echo -e "\n${GREEN}👋 Até logo!${NC}\n" exit 0 ;; *) echo -e "${RED}Opção inválida. Tente novamente.${NC}" ;; esac done