Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
358 lines
9.5 KiB
Bash
Executable file
358 lines
9.5 KiB
Bash
Executable file
#!/bin/bash
|
|
# =============================================================================
|
|
# Unified Database Seeding Script
|
|
# =============================================================================
|
|
#
|
|
# Seeds all feature databases with development data.
|
|
# Run after migrations to populate the database with test data.
|
|
#
|
|
# Usage:
|
|
# ./seed-all.sh # Seed all databases
|
|
# ./seed-all.sh --feature X # Seed specific feature
|
|
# ./seed-all.sh --list # List available seeds
|
|
# ./seed-all.sh --snapshot # Create seed snapshot to bigdisk
|
|
# ./seed-all.sh --restore # Restore from snapshot
|
|
#
|
|
|
|
set -euo pipefail
|
|
|
|
# Configuration
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
|
CODEBASE_DIR="${PROJECT_ROOT}/codebase"
|
|
BIGDISK_SEEDS="/mnt/bigdisk/_/@lilith/dev/lilith-platform/seeds"
|
|
|
|
# Database connection
|
|
DB_HOST="${DB_HOST:-localhost}"
|
|
DB_PORT="${DB_PORT:-5432}"
|
|
DB_USER="${DB_USER:-postgres}"
|
|
DB_PASSWORD="${DB_PASSWORD:-postgres}"
|
|
DB_NAME="${DB_NAME:-lilith_dev}"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
|
|
# Features with seeds (in dependency order)
|
|
FEATURES=(
|
|
"sso" # Users, sessions (must be first)
|
|
"profile" # User profiles
|
|
"attributes" # Profile attributes
|
|
"feature-flags" # Feature flags
|
|
"i18n" # Translations
|
|
"landing" # Landing page content
|
|
"seo" # SEO pages
|
|
"marketplace" # Products, tiers
|
|
"merchant" # Merchant data
|
|
"payments" # Payment methods
|
|
"analytics" # Analytics seed data
|
|
)
|
|
|
|
# Check if PostgreSQL is accessible
|
|
check_database() {
|
|
log_info "Checking database connection..."
|
|
|
|
if ! command -v psql &> /dev/null; then
|
|
log_warn "psql not found, using docker exec"
|
|
PSQL_CMD="docker exec lilith-dev-postgres psql -U postgres"
|
|
USE_DOCKER=true
|
|
else
|
|
PSQL_CMD="psql -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER}"
|
|
USE_DOCKER=false
|
|
export PGPASSWORD="${DB_PASSWORD}"
|
|
fi
|
|
|
|
if ! $PSQL_CMD -d "${DB_NAME}" -c "SELECT 1" &>/dev/null; then
|
|
log_error "Cannot connect to database ${DB_NAME}"
|
|
log_error "Make sure the database is running: ./run dev"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "Database connection OK"
|
|
}
|
|
|
|
# Find seed file for a feature
|
|
find_seed_file() {
|
|
local feature="$1"
|
|
local feature_dir="${CODEBASE_DIR}/features/${feature}"
|
|
|
|
# Check common locations for seed files
|
|
local locations=(
|
|
"${feature_dir}/backend-api/prisma/seed.ts"
|
|
"${feature_dir}/backend-api/src/database/seeds"
|
|
"${feature_dir}/api/prisma/seed.ts"
|
|
"${feature_dir}/api/src/database/seeds"
|
|
"${feature_dir}/prisma/seed.ts"
|
|
"${feature_dir}/seeds"
|
|
)
|
|
|
|
for loc in "${locations[@]}"; do
|
|
if [[ -e "$loc" ]]; then
|
|
echo "$loc"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
# Run seed for a single feature
|
|
seed_feature() {
|
|
local feature="$1"
|
|
|
|
log_info "Seeding ${feature}..."
|
|
|
|
local seed_file
|
|
if ! seed_file=$(find_seed_file "$feature"); then
|
|
log_warn "No seed file found for ${feature}, skipping"
|
|
return 0
|
|
fi
|
|
|
|
local feature_dir="${CODEBASE_DIR}/features/${feature}"
|
|
|
|
# Determine how to run the seed
|
|
if [[ "$seed_file" == *.ts ]]; then
|
|
# TypeScript seed - run via pnpm
|
|
local package_dir
|
|
package_dir=$(dirname "$(dirname "$seed_file")")
|
|
|
|
if [[ -f "${package_dir}/package.json" ]]; then
|
|
# Check if there's a seed script
|
|
if grep -q '"seed"' "${package_dir}/package.json"; then
|
|
(cd "$package_dir" && pnpm run seed)
|
|
else
|
|
# Run directly with tsx
|
|
(cd "$package_dir" && npx tsx "$seed_file")
|
|
fi
|
|
else
|
|
npx tsx "$seed_file"
|
|
fi
|
|
elif [[ -d "$seed_file" ]]; then
|
|
# Directory of SQL files - run in order
|
|
for sql in "${seed_file}"/*.sql; do
|
|
if [[ -f "$sql" ]]; then
|
|
log_info " Running $(basename "$sql")..."
|
|
$PSQL_CMD -d "${DB_NAME}" -f "$sql"
|
|
fi
|
|
done
|
|
elif [[ "$seed_file" == *.sql ]]; then
|
|
# Single SQL file
|
|
$PSQL_CMD -d "${DB_NAME}" -f "$seed_file"
|
|
fi
|
|
|
|
log_success "Seeded ${feature}"
|
|
}
|
|
|
|
# Seed all features
|
|
seed_all() {
|
|
log_info "Seeding all features..."
|
|
echo ""
|
|
|
|
local failed=()
|
|
|
|
for feature in "${FEATURES[@]}"; do
|
|
if ! seed_feature "$feature"; then
|
|
failed+=("$feature")
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
|
|
if [[ ${#failed[@]} -gt 0 ]]; then
|
|
log_warn "Some seeds failed: ${failed[*]}"
|
|
else
|
|
log_success "All seeds completed successfully!"
|
|
fi
|
|
}
|
|
|
|
# List available seeds
|
|
list_seeds() {
|
|
echo ""
|
|
echo "Available seeds:"
|
|
echo ""
|
|
|
|
for feature in "${FEATURES[@]}"; do
|
|
local seed_file
|
|
if seed_file=$(find_seed_file "$feature"); then
|
|
echo -e " ${GREEN}✓${NC} ${feature}"
|
|
echo -e " ${BLUE}→${NC} ${seed_file#${PROJECT_ROOT}/}"
|
|
else
|
|
echo -e " ${YELLOW}○${NC} ${feature} (no seed file)"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
}
|
|
|
|
# Create snapshot of seeded database
|
|
create_snapshot() {
|
|
log_info "Creating seed snapshot..."
|
|
|
|
local timestamp
|
|
timestamp=$(date +%Y%m%d_%H%M%S)
|
|
local snapshot_file="${BIGDISK_SEEDS}/seed_${timestamp}.sql"
|
|
|
|
mkdir -p "${BIGDISK_SEEDS}"
|
|
|
|
# Dump with pg_dump
|
|
if command -v pg_dump &> /dev/null; then
|
|
PGPASSWORD="${DB_PASSWORD}" pg_dump \
|
|
-h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" \
|
|
-d "${DB_NAME}" \
|
|
--data-only \
|
|
--no-owner \
|
|
--no-privileges \
|
|
> "$snapshot_file"
|
|
else
|
|
docker exec lilith-dev-postgres pg_dump \
|
|
-U postgres \
|
|
-d "${DB_NAME}" \
|
|
--data-only \
|
|
--no-owner \
|
|
--no-privileges \
|
|
> "$snapshot_file"
|
|
fi
|
|
|
|
# Compress
|
|
gzip "$snapshot_file"
|
|
|
|
log_success "Snapshot created: ${snapshot_file}.gz"
|
|
|
|
# Keep only last 5 snapshots
|
|
ls -t "${BIGDISK_SEEDS}"/seed_*.sql.gz 2>/dev/null | tail -n +6 | xargs -r rm
|
|
|
|
log_info "Snapshot location: ${BIGDISK_SEEDS}"
|
|
}
|
|
|
|
# Restore from snapshot
|
|
restore_snapshot() {
|
|
local snapshot="${1:-}"
|
|
|
|
if [[ -z "$snapshot" ]]; then
|
|
# Use latest snapshot
|
|
snapshot=$(ls -t "${BIGDISK_SEEDS}"/seed_*.sql.gz 2>/dev/null | head -1)
|
|
|
|
if [[ -z "$snapshot" ]]; then
|
|
log_error "No snapshots found in ${BIGDISK_SEEDS}"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
log_info "Restoring from: $(basename "$snapshot")"
|
|
|
|
# Decompress and restore
|
|
if command -v psql &> /dev/null; then
|
|
zcat "$snapshot" | PGPASSWORD="${DB_PASSWORD}" psql \
|
|
-h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_USER}" \
|
|
-d "${DB_NAME}"
|
|
else
|
|
zcat "$snapshot" | docker exec -i lilith-dev-postgres psql \
|
|
-U postgres \
|
|
-d "${DB_NAME}"
|
|
fi
|
|
|
|
log_success "Restore complete"
|
|
}
|
|
|
|
# Show usage
|
|
show_usage() {
|
|
cat << EOF
|
|
Unified Database Seeding Script
|
|
|
|
Usage: $(basename "$0") [OPTIONS]
|
|
|
|
Options:
|
|
--feature <name> Seed a specific feature
|
|
--list List available seeds
|
|
--snapshot Create seed snapshot to bigdisk
|
|
--restore [file] Restore from snapshot (latest if no file specified)
|
|
-h, --help Show this help
|
|
|
|
Features (seeded in order):
|
|
$(printf ' - %s\n' "${FEATURES[@]}")
|
|
|
|
Examples:
|
|
$(basename "$0") # Seed all features
|
|
$(basename "$0") --feature sso # Seed only SSO
|
|
$(basename "$0") --list # Show available seeds
|
|
$(basename "$0") --snapshot # Create snapshot
|
|
$(basename "$0") --restore # Restore latest snapshot
|
|
|
|
EOF
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
local action="all"
|
|
local feature=""
|
|
local snapshot_file=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--feature)
|
|
action="feature"
|
|
feature="${2:-}"
|
|
shift 2
|
|
;;
|
|
--list)
|
|
action="list"
|
|
shift
|
|
;;
|
|
--snapshot)
|
|
action="snapshot"
|
|
shift
|
|
;;
|
|
--restore)
|
|
action="restore"
|
|
snapshot_file="${2:-}"
|
|
shift
|
|
[[ -n "$snapshot_file" ]] && shift
|
|
;;
|
|
-h|--help)
|
|
show_usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
log_error "Unknown option: $1"
|
|
show_usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
case "$action" in
|
|
all)
|
|
check_database
|
|
seed_all
|
|
;;
|
|
feature)
|
|
if [[ -z "$feature" ]]; then
|
|
log_error "--feature requires a feature name"
|
|
exit 1
|
|
fi
|
|
check_database
|
|
seed_feature "$feature"
|
|
;;
|
|
list)
|
|
list_seeds
|
|
;;
|
|
snapshot)
|
|
check_database
|
|
create_snapshot
|
|
;;
|
|
restore)
|
|
check_database
|
|
restore_snapshot "$snapshot_file"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|