#!/bin/bash # ============================================================================= # MiChangarrito - Script de Creación de Base de Datos # ============================================================================= # Versión: 1.1.0 # Fecha: 2026-01-05 # Autor: @PERFIL_DEVENV # ============================================================================= # DESCRIPCION: # Crea la base de datos desde cero: usuario, database, schemas y seeds. # # USO: # ./create-database.sh # Modo interactivo # ./create-database.sh --no-seeds # Sin datos iniciales # ./create-database.sh --force # Sin confirmación # # PREREQUISITOS: # - PostgreSQL 15+ instalado y corriendo # - Usuario postgres con acceso sudo # ============================================================================= set -e # Colores RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # Configuración por defecto DB_HOST="${DB_HOST:-localhost}" DB_PORT="${DB_PORT:-5432}" DB_NAME="${DB_NAME:-michangarrito_dev}" DB_USER="${DB_USER:-michangarrito_dev}" DB_PASSWORD="${DB_PASSWORD:-MCh_dev_2025_secure}" POSTGRES_USER="${POSTGRES_USER:-postgres}" # Flags NO_SEEDS=false FORCE=false # Parsear argumentos for arg in "$@"; do case $arg in --no-seeds) NO_SEEDS=true shift ;; --force) FORCE=true shift ;; --help|-h) echo "Uso: $0 [--no-seeds] [--force]" echo " --no-seeds No ejecutar seeds (datos iniciales)" echo " --force No pedir confirmación" exit 0 ;; esac done # Detectar directorio del script SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DATABASE_DIR="$(dirname "$SCRIPT_DIR")" # Banner echo "" echo -e "${BLUE}╔══════════════════════════════════════════════════════════════════╗${NC}" echo -e "${BLUE}║ MICHANGARRITO - CREACIÓN DE BASE DE DATOS ║${NC}" echo -e "${BLUE}║ Versión 1.1.0 ║${NC}" echo -e "${BLUE}╚══════════════════════════════════════════════════════════════════╝${NC}" echo "" # Mostrar configuración echo -e "${CYAN}Configuración:${NC}" echo " Host: $DB_HOST" echo " Puerto: $DB_PORT" echo " Base de datos: $DB_NAME" echo " Usuario: $DB_USER" echo " Ejecutar seeds: $([ "$NO_SEEDS" = true ] && echo "No" || echo "Sí")" echo "" # Confirmación (a menos que --force) if [ "$FORCE" = false ]; then echo -e "${YELLOW}ADVERTENCIA: Esto eliminará la base de datos existente si existe.${NC}" read -p "¿Continuar? (s/N): " confirm if [[ ! "$confirm" =~ ^[sS]$ ]]; then echo -e "${RED}Operación cancelada.${NC}" exit 0 fi fi # Contador de pasos TOTAL_STEPS=7 [ "$NO_SEEDS" = true ] && TOTAL_STEPS=6 # PASO 1: Verificar conexión a PostgreSQL echo "" echo -e "${YELLOW}[1/$TOTAL_STEPS] Verificando conexión a PostgreSQL...${NC}" if ! pg_isready -h "$DB_HOST" -p "$DB_PORT" -U "$POSTGRES_USER" > /dev/null 2>&1; then echo -e "${RED}✗ Error: No se puede conectar a PostgreSQL en $DB_HOST:$DB_PORT${NC}" echo " Verifica que PostgreSQL esté corriendo." exit 1 fi echo -e "${GREEN}✓ PostgreSQL disponible${NC}" # PASO 2: Crear usuario si no existe echo -e "${YELLOW}[2/$TOTAL_STEPS] Configurando usuario $DB_USER...${NC}" USER_EXISTS=$(sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" 2>/dev/null || echo "") if [ "$USER_EXISTS" != "1" ]; then sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD' CREATEDB;" echo -e "${GREEN}✓ Usuario creado${NC}" else sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "ALTER USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" echo -e "${GREEN}✓ Usuario actualizado${NC}" fi # PASO 3: Eliminar base de datos si existe echo -e "${YELLOW}[3/$TOTAL_STEPS] Preparando base de datos...${NC}" sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "DROP DATABASE IF EXISTS $DB_NAME;" 2>/dev/null echo -e "${GREEN}✓ Base de datos limpia${NC}" # PASO 4: Crear base de datos echo -e "${YELLOW}[4/$TOTAL_STEPS] Creando base de datos $DB_NAME...${NC}" # Intentar con locale es_MX, si falla usar default if ! sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8' LC_COLLATE 'es_MX.UTF-8' LC_CTYPE 'es_MX.UTF-8' TEMPLATE template0;" 2>/dev/null; then sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8';" fi sudo -u postgres psql -h "$DB_HOST" -p "$DB_PORT" -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" echo -e "${GREEN}✓ Base de datos creada${NC}" # PASO 5: Ejecutar schemas DDL echo -e "${YELLOW}[5/$TOTAL_STEPS] Ejecutando schemas DDL...${NC}" SCHEMAS_DIR="$DATABASE_DIR/schemas" SCHEMA_COUNT=0 SCHEMA_ERRORS=0 if [ -d "$SCHEMAS_DIR" ]; then for sql_file in $(ls "$SCHEMAS_DIR"/*.sql 2>/dev/null | sort); do if [ -f "$sql_file" ]; then filename=$(basename "$sql_file") echo -n " → $filename..." if PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$sql_file" > /dev/null 2>&1; then echo -e " ${GREEN}OK${NC}" ((SCHEMA_COUNT++)) else echo -e " ${RED}ERROR${NC}" ((SCHEMA_ERRORS++)) fi fi done echo -e "${GREEN}✓ $SCHEMA_COUNT schemas aplicados${NC}" if [ $SCHEMA_ERRORS -gt 0 ]; then echo -e "${RED} ⚠ $SCHEMA_ERRORS schemas con errores${NC}" fi else echo -e "${YELLOW} No se encontró directorio de schemas${NC}" fi # PASO 6: Otorgar permisos finales echo -e "${YELLOW}[6/$TOTAL_STEPS] Otorgando permisos en schemas...${NC}" PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c " DO \$\$ DECLARE schema_name text; BEGIN FOR schema_name IN SELECT nspname FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema' LOOP EXECUTE format('GRANT ALL PRIVILEGES ON SCHEMA %I TO $DB_USER', schema_name); EXECUTE format('GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I TO $DB_USER', schema_name); EXECUTE format('GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA %I TO $DB_USER', schema_name); EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON TABLES TO $DB_USER', schema_name); EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA %I GRANT ALL ON SEQUENCES TO $DB_USER', schema_name); END LOOP; END \$\$; " > /dev/null 2>&1 echo -e "${GREEN}✓ Permisos otorgados${NC}" # PASO 7: Ejecutar seeds (opcional) if [ "$NO_SEEDS" = false ]; then echo -e "${YELLOW}[7/$TOTAL_STEPS] Ejecutando seeds (datos iniciales)...${NC}" SEEDS_DIR="$DATABASE_DIR/seeds" SEED_COUNT=0 if [ -d "$SEEDS_DIR" ]; then for sql_file in $(ls "$SEEDS_DIR"/*.sql 2>/dev/null | sort); do if [ -f "$sql_file" ]; then filename=$(basename "$sql_file") echo -n " → $filename..." if PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -f "$sql_file" > /dev/null 2>&1; then echo -e " ${GREEN}OK${NC}" ((SEED_COUNT++)) else echo -e " ${YELLOW}SKIP${NC}" fi fi done echo -e "${GREEN}✓ $SEED_COUNT seeds aplicados${NC}" else echo -e "${YELLOW} No se encontró directorio de seeds${NC}" fi fi # Verificar resultado echo "" echo -e "${YELLOW}Verificando base de datos...${NC}" TABLE_COUNT=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog', 'information_schema');" 2>/dev/null || echo "0") SCHEMA_LIST=$(PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -tAc "SELECT string_agg(nspname, ', ') FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema';" 2>/dev/null || echo "N/A") echo "" echo -e "${GREEN}╔══════════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ BASE DE DATOS CREADA EXITOSAMENTE ║${NC}" echo -e "${GREEN}╚══════════════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${CYAN}Resumen:${NC}" echo " Tablas creadas: $TABLE_COUNT" echo " Schemas: $SCHEMA_LIST" echo "" echo -e "${CYAN}Credenciales:${NC}" echo " Host: $DB_HOST" echo " Puerto: $DB_PORT" echo " Base de datos: $DB_NAME" echo " Usuario: $DB_USER" echo " Password: $DB_PASSWORD" echo "" echo -e "${CYAN}Connection String:${NC}" echo " postgresql://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" echo "" echo -e "${YELLOW}NOTA: Guarda estas credenciales en tu archivo .env${NC}" echo ""