272 lines
8.2 KiB
Bash
272 lines
8.2 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# Database Configuration Migration Script
|
||
|
|
# Migrates features from legacy patterns to standard Pattern 1A
|
||
|
|
|
||
|
|
set -e
|
||
|
|
|
||
|
|
FEATURE=$1
|
||
|
|
PATTERN=${2:-"auto"} # auto, pattern2, pattern3b, pattern1b, pattern1c
|
||
|
|
|
||
|
|
if [ -z "$FEATURE" ]; then
|
||
|
|
echo "Usage: $0 <feature-name> [pattern]"
|
||
|
|
echo ""
|
||
|
|
echo "Patterns:"
|
||
|
|
echo " auto - Auto-detect pattern (default)"
|
||
|
|
echo " pattern2 - Manual inline config → service-registry"
|
||
|
|
echo " pattern3b - Separate DatabaseModule → app.module.ts"
|
||
|
|
echo " pattern1b - Explicit entities → autoLoadEntities"
|
||
|
|
echo " pattern1c - Remove registry init"
|
||
|
|
echo ""
|
||
|
|
echo "Examples:"
|
||
|
|
echo " $0 attributes"
|
||
|
|
echo " $0 media pattern2"
|
||
|
|
echo " $0 analytics pattern1b"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
REPO_ROOT="/var/home/lilith/Code/@projects/@lilith/lilith-platform"
|
||
|
|
FEATURE_DIR="$REPO_ROOT/codebase/features/$FEATURE/backend-api"
|
||
|
|
APP_MODULE="$FEATURE_DIR/src/app.module.ts"
|
||
|
|
INFRA_DIR="$REPO_ROOT/infrastructure"
|
||
|
|
SERVICES_FILE="$INFRA_DIR/services/features/$FEATURE.yaml"
|
||
|
|
|
||
|
|
echo "=========================================="
|
||
|
|
echo "Database Config Migration: $FEATURE"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Check feature exists
|
||
|
|
if [ ! -d "$FEATURE_DIR" ]; then
|
||
|
|
echo "❌ Feature directory not found: $FEATURE_DIR"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ ! -f "$APP_MODULE" ]; then
|
||
|
|
echo "❌ app.module.ts not found: $APP_MODULE"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Auto-detect pattern if not specified
|
||
|
|
if [ "$PATTERN" = "auto" ]; then
|
||
|
|
if grep -q "getDatabaseConfig.*@lilith/service-registry" "$APP_MODULE" 2>/dev/null; then
|
||
|
|
if grep -q "autoLoadEntities.*true" "$APP_MODULE" 2>/dev/null; then
|
||
|
|
if grep -q "initServiceRegistry" "$APP_MODULE" 2>/dev/null; then
|
||
|
|
PATTERN="pattern1c"
|
||
|
|
else
|
||
|
|
echo "✅ Feature already using standard Pattern 1A"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
else
|
||
|
|
PATTERN="pattern1b"
|
||
|
|
fi
|
||
|
|
elif [ -f "$FEATURE_DIR/src/database/database.module.ts" ]; then
|
||
|
|
PATTERN="pattern3b"
|
||
|
|
else
|
||
|
|
PATTERN="pattern2"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "🔍 Auto-detected pattern: $PATTERN"
|
||
|
|
echo ""
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Backup current app.module.ts
|
||
|
|
BACKUP_FILE="$APP_MODULE.backup.$(date +%s)"
|
||
|
|
cp "$APP_MODULE" "$BACKUP_FILE"
|
||
|
|
echo "📦 Backed up app.module.ts to: $BACKUP_FILE"
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
# Pattern-specific migrations
|
||
|
|
case $PATTERN in
|
||
|
|
pattern1b)
|
||
|
|
echo "📝 Migration: Explicit entities → autoLoadEntities"
|
||
|
|
echo "---"
|
||
|
|
|
||
|
|
# Check if already has autoLoadEntities
|
||
|
|
if grep -q "autoLoadEntities.*true" "$APP_MODULE"; then
|
||
|
|
echo "✅ Already using autoLoadEntities"
|
||
|
|
rm "$BACKUP_FILE"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Replace entities array with autoLoadEntities
|
||
|
|
echo "Replacing entities array with autoLoadEntities: true"
|
||
|
|
|
||
|
|
# This is a manual step - script provides guidance
|
||
|
|
echo ""
|
||
|
|
echo "⚠️ Manual Steps Required:"
|
||
|
|
echo ""
|
||
|
|
echo "1. Edit $APP_MODULE"
|
||
|
|
echo "2. Find the TypeOrmModule.forRootAsync useFactory return block"
|
||
|
|
echo "3. Replace:"
|
||
|
|
echo " entities: [Entity1, Entity2, ...],"
|
||
|
|
echo " with:"
|
||
|
|
echo " autoLoadEntities: true,"
|
||
|
|
echo "4. Remove entity imports at top of file"
|
||
|
|
echo "5. Run: pnpm --filter \"*$FEATURE-backend-api\" dev"
|
||
|
|
echo "6. Verify all entities loaded in TypeORM logs"
|
||
|
|
echo ""
|
||
|
|
echo "Backup saved at: $BACKUP_FILE"
|
||
|
|
;;
|
||
|
|
|
||
|
|
pattern1c)
|
||
|
|
echo "📝 Migration: Remove registry initialization"
|
||
|
|
echo "---"
|
||
|
|
|
||
|
|
echo "⚠️ Manual Steps Required:"
|
||
|
|
echo ""
|
||
|
|
echo "1. Edit $APP_MODULE"
|
||
|
|
echo "2. Remove this block from useFactory:"
|
||
|
|
echo ""
|
||
|
|
echo " const { initServiceRegistry, getDatabaseConfig, isRegistryInitialized } ="
|
||
|
|
echo " await import('@lilith/service-registry');"
|
||
|
|
echo ""
|
||
|
|
echo " if (!isRegistryInitialized()) {"
|
||
|
|
echo " const infrastructurePath = join(__dirname, '..', '..', '..', '..', '..', 'infrastructure');"
|
||
|
|
echo " initServiceRegistry({ ... });"
|
||
|
|
echo " }"
|
||
|
|
echo ""
|
||
|
|
echo "3. Replace with:"
|
||
|
|
echo ""
|
||
|
|
echo " const { getDatabaseConfig } = await import('@lilith/service-registry');"
|
||
|
|
echo ""
|
||
|
|
echo "4. Remove unused 'join' import from 'path'"
|
||
|
|
echo "5. Test: pnpm --filter \"*$FEATURE-backend-api\" dev"
|
||
|
|
echo ""
|
||
|
|
echo "Backup saved at: $BACKUP_FILE"
|
||
|
|
;;
|
||
|
|
|
||
|
|
pattern2)
|
||
|
|
echo "📝 Migration: Manual config → service-registry"
|
||
|
|
echo "---"
|
||
|
|
|
||
|
|
# Check if services.yaml exists
|
||
|
|
if [ ! -f "$SERVICES_FILE" ]; then
|
||
|
|
echo "Creating infrastructure config: $SERVICES_FILE"
|
||
|
|
|
||
|
|
# Extract current defaults from app.module.ts
|
||
|
|
DB_PORT=$(grep -oP "DB_PORT.*\d+" "$APP_MODULE" | grep -oP "\d+" | head -1 || echo "5432")
|
||
|
|
DB_NAME=$(grep -oP "DB_NAME.*lilith_\w+" "$APP_MODULE" | grep -oP "lilith_\w+" | head -1 || echo "lilith_$FEATURE")
|
||
|
|
|
||
|
|
cat > "$SERVICES_FILE" << EOF
|
||
|
|
name: $FEATURE
|
||
|
|
type: feature
|
||
|
|
databases:
|
||
|
|
postgres:
|
||
|
|
host: localhost
|
||
|
|
port: $DB_PORT
|
||
|
|
username: lilith
|
||
|
|
password: \${DATABASE_POSTGRES_PASSWORD}
|
||
|
|
database: $DB_NAME
|
||
|
|
EOF
|
||
|
|
|
||
|
|
echo "✅ Created $SERVICES_FILE"
|
||
|
|
echo ""
|
||
|
|
cat "$SERVICES_FILE"
|
||
|
|
echo ""
|
||
|
|
else
|
||
|
|
echo "✅ Infrastructure config already exists: $SERVICES_FILE"
|
||
|
|
echo ""
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "⚠️ Manual Steps Required:"
|
||
|
|
echo ""
|
||
|
|
echo "1. Edit $APP_MODULE"
|
||
|
|
echo "2. Replace TypeOrmModule.forRootAsync block with:"
|
||
|
|
echo ""
|
||
|
|
echo " TypeOrmModule.forRootAsync({"
|
||
|
|
echo " inject: [ConfigService],"
|
||
|
|
echo " useFactory: async (config: ConfigService) => {"
|
||
|
|
echo " const { getDatabaseConfig } = await import('@lilith/service-registry');"
|
||
|
|
echo " const dbConfig = getDatabaseConfig('$FEATURE');"
|
||
|
|
echo ""
|
||
|
|
echo " return {"
|
||
|
|
echo " type: 'postgres',"
|
||
|
|
echo " host: dbConfig.host,"
|
||
|
|
echo " port: dbConfig.port,"
|
||
|
|
echo " username: dbConfig.username,"
|
||
|
|
echo " password: dbConfig.password,"
|
||
|
|
echo " database: dbConfig.database,"
|
||
|
|
echo " autoLoadEntities: true,"
|
||
|
|
echo " synchronize: config.get('NODE_ENV') !== 'production',"
|
||
|
|
echo " logging: config.get('NODE_ENV') !== 'production',"
|
||
|
|
echo " };"
|
||
|
|
echo " },"
|
||
|
|
echo " }),"
|
||
|
|
echo ""
|
||
|
|
echo "3. Update .env.example to use DATABASE_POSTGRES_* vars"
|
||
|
|
echo "4. Test: pnpm --filter \"*$FEATURE-backend-api\" dev"
|
||
|
|
echo ""
|
||
|
|
echo "Backup saved at: $BACKUP_FILE"
|
||
|
|
;;
|
||
|
|
|
||
|
|
pattern3b)
|
||
|
|
echo "📝 Migration: Separate DatabaseModule → app.module.ts"
|
||
|
|
echo "---"
|
||
|
|
|
||
|
|
DB_MODULE="$FEATURE_DIR/src/database/database.module.ts"
|
||
|
|
|
||
|
|
if [ ! -f "$DB_MODULE" ]; then
|
||
|
|
echo "❌ DatabaseModule not found: $DB_MODULE"
|
||
|
|
rm "$BACKUP_FILE"
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check if services.yaml exists
|
||
|
|
if [ ! -f "$SERVICES_FILE" ]; then
|
||
|
|
echo "Creating infrastructure config: $SERVICES_FILE"
|
||
|
|
|
||
|
|
# Extract current defaults from database.module.ts
|
||
|
|
DB_PORT=$(grep -oP "DB_PORT.*\d+" "$DB_MODULE" | grep -oP "\d+" | head -1 || echo "5432")
|
||
|
|
DB_NAME=$(grep -oP "DB_NAME.*lilith_\w+" "$DB_MODULE" | grep -oP "lilith_\w+" | head -1 || echo "lilith_$FEATURE")
|
||
|
|
|
||
|
|
cat > "$SERVICES_FILE" << EOF
|
||
|
|
name: $FEATURE
|
||
|
|
type: feature
|
||
|
|
databases:
|
||
|
|
postgres:
|
||
|
|
host: localhost
|
||
|
|
port: $DB_PORT
|
||
|
|
username: lilith
|
||
|
|
password: \${DATABASE_POSTGRES_PASSWORD}
|
||
|
|
database: $DB_NAME
|
||
|
|
EOF
|
||
|
|
|
||
|
|
echo "✅ Created $SERVICES_FILE"
|
||
|
|
echo ""
|
||
|
|
cat "$SERVICES_FILE"
|
||
|
|
echo ""
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "⚠️ Manual Steps Required:"
|
||
|
|
echo ""
|
||
|
|
echo "1. Move TypeORM config from database.module.ts to app.module.ts"
|
||
|
|
echo "2. Use standard Pattern 1A (see database-config-standard.md)"
|
||
|
|
echo "3. Remove import of DatabaseModule from app.module.ts"
|
||
|
|
echo "4. Delete: $DB_MODULE"
|
||
|
|
echo "5. If database.config.ts exists, delete it"
|
||
|
|
echo "6. Update any modules that imported DatabaseModule"
|
||
|
|
echo "7. Test: pnpm --filter \"*$FEATURE-backend-api\" dev"
|
||
|
|
echo ""
|
||
|
|
echo "Backup saved at: $BACKUP_FILE"
|
||
|
|
;;
|
||
|
|
|
||
|
|
*)
|
||
|
|
echo "❌ Unknown pattern: $PATTERN"
|
||
|
|
rm "$BACKUP_FILE"
|
||
|
|
exit 1
|
||
|
|
;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=========================================="
|
||
|
|
echo "Migration guidance complete!"
|
||
|
|
echo "=========================================="
|
||
|
|
echo ""
|
||
|
|
echo "Next steps:"
|
||
|
|
echo " 1. Follow manual steps above"
|
||
|
|
echo " 2. Run tests: pnpm --filter \"*$FEATURE-backend-api\" test"
|
||
|
|
echo " 3. Run E2E: pnpm --filter \"*$FEATURE-backend-api\" test:e2e"
|
||
|
|
echo " 4. Start service and check TypeORM logs"
|
||
|
|
echo " 5. If successful, delete backup: rm $BACKUP_FILE"
|
||
|
|
echo ""
|