Rustelo/scripts/databases/db-setup.sh

389 lines
9.7 KiB
Bash
Raw Normal View History

2025-07-07 23:53:50 +01:00
#!/bin/bash
# Database Setup Script
# Provides convenient commands for database management
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
# Change to project root
cd "$PROJECT_ROOT"
# Logging functions
log() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
print_header() {
echo -e "${BLUE}=== $1 ===${NC}"
}
print_usage() {
echo "Database Setup Script"
echo
echo "Usage: $0 <command> [options]"
echo
echo "Commands:"
echo " setup Full database setup (create + migrate + seed)"
echo " create Create the database"
echo " migrate Run migrations"
echo " seed Seed database with test data"
echo " reset Reset database (drop + create + migrate)"
echo " status Show migration status"
echo " drop Drop the database"
echo " postgres Setup PostgreSQL database"
echo " sqlite Setup SQLite database"
echo
echo "Options:"
echo " --env ENV Environment (dev/prod) [default: dev]"
echo " --force Skip confirmations"
echo " --quiet Suppress verbose output"
echo
echo "Examples:"
echo " $0 setup # Full setup with default settings"
echo " $0 migrate # Run pending migrations"
echo " $0 reset --force # Reset database without confirmation"
echo " $0 postgres # Setup PostgreSQL specifically"
echo " $0 sqlite # Setup SQLite specifically"
}
# Check if .env file exists
check_env_file() {
if [ ! -f ".env" ]; then
log_warn ".env file not found"
log "Creating .env file from template..."
if [ -f ".env.example" ]; then
cp ".env.example" ".env"
log "Created .env from .env.example"
else
create_default_env
fi
fi
}
# Create default .env file
create_default_env() {
cat > ".env" << EOF
# Environment Configuration
ENVIRONMENT=dev
# Database Configuration
DATABASE_URL=postgresql://dev:dev@localhost:5432/rustelo_dev
# Server Configuration
SERVER_HOST=127.0.0.1
SERVER_PORT=3030
SERVER_PROTOCOL=http
# Session Configuration
SESSION_SECRET=dev-secret-not-for-production
# Features
ENABLE_AUTH=true
ENABLE_CONTENT_DB=true
ENABLE_TLS=false
# Logging
LOG_LEVEL=debug
RUST_LOG=debug
EOF
log "Created default .env file"
}
# Check dependencies
check_dependencies() {
local missing=()
if ! command -v cargo >/dev/null 2>&1; then
missing+=("cargo (Rust)")
fi
if ! command -v psql >/dev/null 2>&1 && ! command -v sqlite3 >/dev/null 2>&1; then
missing+=("psql (PostgreSQL) or sqlite3")
fi
if [ ${#missing[@]} -gt 0 ]; then
log_error "Missing dependencies: ${missing[*]}"
echo
echo "Please install the missing dependencies:"
echo "- Rust: https://rustup.rs/"
echo "- PostgreSQL: https://postgresql.org/download/"
echo "- SQLite: Usually pre-installed or via package manager"
exit 1
fi
}
# Setup PostgreSQL database
setup_postgresql() {
print_header "Setting up PostgreSQL Database"
# Check if PostgreSQL is running
if ! pg_isready >/dev/null 2>&1; then
log_warn "PostgreSQL is not running"
echo "Please start PostgreSQL service:"
echo " macOS (Homebrew): brew services start postgresql"
echo " Linux (systemd): sudo systemctl start postgresql"
echo " Windows: Start PostgreSQL service from Services panel"
exit 1
fi
# Create development user if it doesn't exist
if ! psql -U postgres -tc "SELECT 1 FROM pg_user WHERE usename = 'dev'" | grep -q 1; then
log "Creating development user..."
psql -U postgres -c "CREATE USER dev WITH PASSWORD 'dev' CREATEDB;"
fi
# Update DATABASE_URL in .env
if grep -q "sqlite://" .env; then
log "Updating .env to use PostgreSQL..."
sed -i.bak 's|DATABASE_URL=.*|DATABASE_URL=postgresql://dev:dev@localhost:5432/rustelo_dev|' .env
rm -f .env.bak
fi
log "PostgreSQL setup complete"
}
# Setup SQLite database
setup_sqlite() {
print_header "Setting up SQLite Database"
# Create data directory
mkdir -p data
# Update DATABASE_URL in .env
if grep -q "postgresql://" .env; then
log "Updating .env to use SQLite..."
sed -i.bak 's|DATABASE_URL=.*|DATABASE_URL=sqlite://data/rustelo.db|' .env
rm -f .env.bak
fi
log "SQLite setup complete"
}
# Run database tool command
run_db_tool() {
local command="$1"
log "Running: cargo run --bin db_tool -- $command"
if [ "$QUIET" = "true" ]; then
cargo run --bin db_tool -- "$command" >/dev/null 2>&1
else
cargo run --bin db_tool -- "$command"
fi
}
# Create seed directory and files if they don't exist
setup_seeds() {
if [ ! -d "seeds" ]; then
log "Creating seeds directory..."
mkdir -p seeds
# Create sample seed files
cat > "seeds/001_sample_users.sql" << EOF
-- Sample users for development
-- This file works for both PostgreSQL and SQLite
INSERT INTO users (username, email, password_hash, is_active, is_verified) VALUES
('admin', 'admin@example.com', '\$argon2id\$v=19\$m=65536,t=3,p=4\$Ym9vZm9v\$2RmTUplMXB3YUNGeFczL1NyTlJFWERsZVdrbUVuNHhDNlk5K1ZZWVorUT0', true, true),
('user', 'user@example.com', '\$argon2id\$v=19\$m=65536,t=3,p=4\$Ym9vZm9v\$2RmTUplMXB3YUNGeFczL1NyTlJFWERsZVdrbUVuNHhDNlk5K1ZZWVorUT0', true, true),
('editor', 'editor@example.com', '\$argon2id\$v=19\$m=65536,t=3,p=4\$Ym9vZm9v\$2RmTUplMXB3YUNGeFczL1NyTlJFWERsZVdrbUVuNHhDNlk5K1ZZWVorUT0', true, true)
ON CONFLICT (email) DO NOTHING;
EOF
cat > "seeds/002_sample_content.sql" << EOF
-- Sample content for development
-- This file works for both PostgreSQL and SQLite
INSERT INTO content (title, slug, content_type, body, is_published, published_at) VALUES
('Welcome to Rustelo', 'welcome', 'markdown', '# Welcome to Rustelo
This is a sample content page created by the seed data.
## Features
- Fast and secure
- Built with Rust
- Modern web framework
- Easy to use
Enjoy building with Rustelo!', true, CURRENT_TIMESTAMP),
('About Us', 'about', 'markdown', '# About Us
This is the about page for your Rustelo application.
You can edit this content through the admin interface or by modifying the seed files.', true, CURRENT_TIMESTAMP),
('Getting Started', 'getting-started', 'markdown', '# Getting Started
Here are some tips to get you started with your new Rustelo application:
1. Check out the admin interface
2. Create your first content
3. Customize the design
4. Deploy to production
Good luck!', false, NULL)
ON CONFLICT (slug) DO NOTHING;
EOF
log "Created sample seed files"
fi
}
# Main setup function
full_setup() {
print_header "Full Database Setup"
check_env_file
setup_seeds
log "Creating database..."
run_db_tool "create"
log "Running migrations..."
run_db_tool "migrate"
log "Seeding database..."
run_db_tool "seed"
log "Checking status..."
run_db_tool "status"
print_header "Setup Complete!"
log "Database is ready for development"
echo
log "Next steps:"
echo " 1. Start the server: cargo leptos watch"
echo " 2. Open http://localhost:3030 in your browser"
echo " 3. Check the database status: $0 status"
}
# Parse command line arguments
COMMAND=""
ENVIRONMENT="dev"
FORCE=false
QUIET=false
while [[ $# -gt 0 ]]; do
case $1 in
--env)
ENVIRONMENT="$2"
shift 2
;;
--force)
FORCE=true
shift
;;
--quiet)
QUIET=true
shift
;;
-h|--help)
print_usage
exit 0
;;
*)
if [ -z "$COMMAND" ]; then
COMMAND="$1"
else
log_error "Unknown option: $1"
print_usage
exit 1
fi
shift
;;
esac
done
# Set environment variable
export ENVIRONMENT="$ENVIRONMENT"
# Validate command
if [ -z "$COMMAND" ]; then
print_usage
exit 1
fi
# Check dependencies
check_dependencies
# Check if we're in the right directory
if [ ! -f "Cargo.toml" ]; then
log_error "Please run this script from the project root directory"
exit 1
fi
# Execute command
case "$COMMAND" in
"setup")
full_setup
;;
"create")
print_header "Creating Database"
check_env_file
run_db_tool "create"
;;
"migrate")
print_header "Running Migrations"
run_db_tool "migrate"
;;
"seed")
print_header "Seeding Database"
setup_seeds
run_db_tool "seed"
;;
"reset")
print_header "Resetting Database"
if [ "$FORCE" != "true" ]; then
echo -n "This will destroy all data. Are you sure? (y/N): "
read -r confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
log "Reset cancelled"
exit 0
fi
fi
run_db_tool "reset"
;;
"status")
print_header "Database Status"
run_db_tool "status"
;;
"drop")
print_header "Dropping Database"
run_db_tool "drop"
;;
"postgres")
setup_postgresql
full_setup
;;
"sqlite")
setup_sqlite
full_setup
;;
*)
log_error "Unknown command: $COMMAND"
print_usage
exit 1
;;
esac