Makefile
Rama main · réplica de lectura del repositorio original.
.PHONY: help setup start stop restart logs clean clean-build-cache test build migrate admin seed-demo quick-dev quick-start upgrade db-backup
# Variables
DOCKER_COMPOSE = docker compose
DOCKER_COMPOSE_DEV = docker compose -f docker-compose.yml -f docker-compose.dev.yml
DOCKER_EXEC_BACKEND = docker exec seneca-backend
DOCKER_EXEC_FRONTEND = docker exec -it seneca-frontend
DOCKER_EXEC_DB = docker exec -it seneca-postgres
define wait_for_backend
@echo "⏳ Waiting for backend to become ready..."
@port=$$(grep -E '^BACKEND_PORT=' .env 2>/dev/null | cut -d= -f2); port=$${port:-3001}; \
for i in $$(seq 1 120); do \
if curl -sf "http://localhost:$$port/api/v1/health/ready" >/dev/null 2>&1; then \
break; \
fi; \
sleep 1; \
done
endef
define wait_for_users_table
@echo "⏳ Waiting for database schema..."
@for i in $$(seq 1 60); do \
if docker exec seneca-postgres psql -U finflow -d finflow -tAc "select 1 from information_schema.tables where table_schema='public' and table_name='users'" 2>/dev/null | grep -q 1; then \
break; \
fi; \
sleep 2; \
done
endef
##@ General
help: ## Display this help message
@awk 'BEGIN {FS = ":.*##"; printf "\n\033[1m\033[36mUsage:\033[0m\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
##@ Setup
setup: ## Initial setup - copy env files and generate secrets
@echo "🚀 Setting up Stoic Budget..."
@npm run setup:env
@echo "✅ Setup complete!"
install: ## Install dependencies (local development)
@echo "📦 Installing dependencies..."
@cd backend && npm install
@cd frontend && npm install
@echo "✅ Dependencies installed!"
##@ Docker Operations
start: ## Start all services in production mode
@echo "🐳 Starting Stoic Budget (production mode)..."
@touch .env
@$(DOCKER_COMPOSE) up -d --build
$(call wait_for_backend)
@echo "✅ Stoic Budget is running!"
@echo "Frontend: http://localhost:3000"
@echo "Backend: http://localhost:3001/api/v1"
@echo "Swagger: http://localhost:3001/api/docs"
upgrade: ## Pull release images from GHCR and restart (pin a version: make upgrade VERSION=v1.2.0)
@touch .env
@$(MAKE) --no-print-directory db-backup
@tag=$${VERSION:-$$(grep -E '^IMAGE_TAG=' .env 2>/dev/null | cut -d= -f2)}; tag=$${tag:-latest}; \
echo "⬇️ Pulling Stoic Budget $$tag..."; \
IMAGE_TAG=$$tag $(DOCKER_COMPOSE) pull backend frontend && \
IMAGE_TAG=$$tag $(DOCKER_COMPOSE) up -d --no-build --remove-orphans
@echo "⏳ Waiting for backend (migrations run on start)..."
@port=$$(grep -E '^BACKEND_PORT=' .env 2>/dev/null | cut -d= -f2); port=$${port:-3001}; \
for i in $$(seq 1 300); do \
curl -sf "http://localhost:$$port/api/v1/health/ready" >/dev/null 2>&1 && { echo "✅ Stoic Budget upgraded"; exit 0; }; \
sleep 1; \
done; \
echo "❌ Backend not ready after 5 min: docker logs seneca-backend"; exit 1
@docker image prune -f >/dev/null
dev: ## Start all services in development mode (with hot reload)
@echo "🐳 Starting Stoic Budget (development mode)..."
@touch .env
@$(DOCKER_COMPOSE_DEV) up -d --build
$(call wait_for_backend)
@echo "✅ Stoic Budget is running in development mode!"
@echo "Frontend: http://localhost:3000"
@echo "Backend: http://localhost:3001/api/v1"
@echo "Swagger: http://localhost:3001/api/docs"
@echo "Run 'make seed-demo' to create demo@seneca.dev / demo123"
stop: ## Stop all services
@echo "🛑 Stopping Stoic Budget..."
@$(DOCKER_COMPOSE) down
@echo "✅ Services stopped!"
restart: ## Restart all services
@echo "🔄 Restarting Stoic Budget..."
@$(DOCKER_COMPOSE) restart
@echo "✅ Services restarted!"
clean-build-cache: ## Remove unused Docker build cache (safe; next build re-creates what it needs)
@docker builder prune -f
@echo "✅ Build cache pruned!"
clean: ## Stop services and remove volumes (also resets the dev node_modules volumes)
@echo "🧹 Cleaning up Stoic Budget..."
@$(DOCKER_COMPOSE_DEV) down -v --remove-orphans
@$(DOCKER_COMPOSE) down -v --remove-orphans
@echo "✅ Cleanup complete!"
##@ Logs
logs: ## View logs from all services
@$(DOCKER_COMPOSE) logs -f
logs-backend: ## View backend logs
@$(DOCKER_COMPOSE) logs -f backend
logs-frontend: ## View frontend logs
@$(DOCKER_COMPOSE) logs -f frontend
logs-db: ## View database logs
@$(DOCKER_COMPOSE) logs -f postgres
logs-redis: ## View Redis logs
@$(DOCKER_COMPOSE) logs -f redis
##@ Development (Local)
backend-dev: ## Start backend in development mode (local)
@echo "🚀 Starting backend in dev mode..."
@cd backend && npm run start:dev
frontend-dev: ## Start frontend in development mode (local)
@echo "🚀 Starting frontend in dev mode..."
@cd frontend && npm run dev
db-start: ## Start only PostgreSQL and Redis
@echo "🐘 Starting database services..."
@$(DOCKER_COMPOSE) up -d postgres redis
@echo "✅ Database services started!"
##@ Database
migrate: ## Run database migrations
@echo "🔄 Running migrations..."
@$(DOCKER_EXEC_BACKEND) npm run migration:run
@echo "✅ Migrations complete!"
migrate-revert: ## Revert last migration
@echo "⏪ Reverting last migration..."
@$(DOCKER_EXEC_BACKEND) npm run migration:revert
@echo "✅ Migration reverted!"
migrate-generate: ## Generate a new migration (usage: make migrate-generate name=MigrationName)
@if [ -z "$(name)" ]; then \
echo "❌ Error: Migration name required. Usage: make migrate-generate name=MigrationName"; \
exit 1; \
fi
@echo "📝 Generating migration: $(name)..."
@$(DOCKER_EXEC_BACKEND) npm run migration:generate -- $(name)
@echo "✅ Migration generated!"
db-shell: ## Open PostgreSQL shell
@echo "🐘 Opening database shell..."
@$(DOCKER_EXEC_DB) psql -U finflow -d finflow
db-backup: ## Backup database
@echo "💾 Creating database backup..."
@# By service, not container name: containers were renamed finflow-* -> seneca-*,
@# and the first upgrade after that still finds the old one running.
@file=backup_$$(date +%Y%m%d_%H%M%S).sql; \
$(DOCKER_COMPOSE) exec -T postgres sh -c 'pg_dump -U "$$POSTGRES_USER" "$$POSTGRES_DB"' > $$file || { rm -f $$file; exit 1; }; \
echo "✅ Backup created: $$file"
db-restore: ## Restore database (usage: make db-restore file=backup.sql)
@if [ -z "$(file)" ]; then \
echo "❌ Error: Backup file required. Usage: make db-restore file=backup.sql"; \
exit 1; \
fi
@echo "📥 Restoring database from $(file)..."
@cat $(file) | $(DOCKER_COMPOSE) exec -T postgres sh -c 'psql -U "$$POSTGRES_USER" "$$POSTGRES_DB"'
@echo "✅ Database restored!"
##@ User Management
admin: ## Create admin user (usage: make admin email=admin@example.com password=admin123 name="Admin")
@if [ -z "$(email)" ] || [ -z "$(password)" ] || [ -z "$(name)" ]; then \
echo "❌ Error: All parameters required."; \
echo "Usage: make admin email=admin@example.com password=admin123 name=\"Admin User\""; \
exit 1; \
fi
@echo "👤 Creating admin user..."
$(call wait_for_users_table)
@if docker inspect -f '{{.State.Running}}' seneca-backend >/dev/null 2>&1; then \
if [ "$$(docker exec seneca-backend printenv NODE_ENV 2>/dev/null)" = "development" ]; then \
docker exec seneca-backend sh -lc 'NODE_OPTIONS=--max-old-space-size=2048 npm run create-admin:dev -- $(email) $(password) "$(name)"'; \
elif docker exec seneca-backend sh -lc 'test -f dist/scripts/create-admin.js'; then \
docker exec seneca-backend node dist/scripts/create-admin.js $(email) $(password) "$(name)"; \
else \
echo "❌ No create-admin entrypoint available in seneca-backend"; \
exit 1; \
fi; \
else \
cd backend && npm run create-admin -- $(email) $(password) "$(name)"; \
fi
@echo "✅ Admin user created!"
seed-demo: ## Create demo user (demo@seneca.dev / demo123)
@echo "👤 Creating demo user..."
$(call wait_for_users_table)
@if docker inspect -f '{{.State.Running}}' seneca-backend >/dev/null 2>&1; then \
if [ "$$(docker exec seneca-backend printenv NODE_ENV 2>/dev/null)" = "development" ]; then \
docker exec seneca-backend sh -lc 'NODE_OPTIONS=--max-old-space-size=2048 npm run seed:demo:dev'; \
elif docker exec seneca-backend sh -lc 'test -f dist/scripts/seed-demo.js'; then \
docker exec seneca-backend node dist/scripts/seed-demo.js; \
else \
echo "❌ No seed-demo entrypoint available in seneca-backend"; \
exit 1; \
fi; \
else \
cd backend && npm run build:scripts && npm run seed:demo; \
fi
@echo "✅ Demo user is ready!"
##@ Testing
test: ## Run all tests
@echo "🧪 Running tests..."
@cd backend && npm test
@cd frontend && npm test
@echo "✅ Tests complete!"
test-backend: ## Run backend tests
@echo "🧪 Running backend tests..."
@cd backend && npm test
test-frontend: ## Run frontend tests
@echo "🧪 Running frontend tests..."
@cd frontend && npm test
test-watch: ## Run backend tests in watch mode
@echo "🧪 Running tests in watch mode..."
@cd backend && npm run test:watch
test-cov: ## Run tests with coverage
@echo "🧪 Running tests with coverage..."
@cd backend && npm run test:cov
@echo "📊 Coverage report: backend/coverage/lcov-report/index.html"
test-e2e: ## Run end-to-end tests
@echo "🧪 Running E2E tests..."
@cd backend && npm run test:e2e
##@ Code Quality
lint: ## Lint and fix code
@echo "🔍 Linting code (Biome)..."
@cd backend && npm run lint
@cd frontend && npm run lint
@echo "✅ Linting complete!"
lint-check: ## Check linting without fixing
@echo "🔍 Checking linting (Biome)..."
@cd backend && npm run lint:check
@cd frontend && npm run lint:check
@echo "✅ Linting check complete!"
format: ## Format code with Biome
@echo "✨ Formatting code..."
@cd backend && npm run format
@cd frontend && npm run format
@echo "✅ Formatting complete!"
type-check: ## Run TypeScript type checking
@echo "🔍 Type checking..."
@cd backend && npm run build
@cd frontend && npm run type-check || echo "No type-check script"
@echo "✅ Type checking complete!"
##@ Build
build: ## Build for production
@echo "🏗️ Building Stoic Budget..."
@cd backend && npm run build
@cd frontend && npm run build
@echo "✅ Build complete!"
build-docker: ## Build Docker images
@echo "🐳 Building Docker images..."
@$(DOCKER_COMPOSE) build
@echo "✅ Docker images built!"
##@ Utilities
shell-backend: ## Open shell in backend container
@$(DOCKER_EXEC_BACKEND) bash
shell-frontend: ## Open shell in frontend container
@$(DOCKER_EXEC_FRONTEND) sh
shell-db: ## Open shell in database container
@$(DOCKER_EXEC_DB) bash
health: ## Check health of all services
@echo "🏥 Checking service health..."
@echo "\n📡 Backend:"
@curl -s http://localhost:3001/api/v1/health || echo "❌ Backend not responding"
@echo "\n🌐 Frontend:"
@curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 || echo "❌ Frontend not responding"
@echo "\n🐘 PostgreSQL:"
@$(DOCKER_EXEC_DB) pg_isready -U finflow || echo "❌ PostgreSQL not ready"
@echo "\n🔴 Redis:"
@docker exec seneca-redis redis-cli ping || echo "❌ Redis not responding"
@echo ""
ps: ## Show running containers
@$(DOCKER_COMPOSE) ps
stats: ## Show container resource usage
@docker stats --no-stream seneca-backend seneca-frontend seneca-postgres seneca-redis
##@ Documentation
docs: ## Open API documentation
@echo "📚 Opening Swagger documentation..."
@open http://localhost:3001/api/docs || xdg-open http://localhost:3001/api/docs || echo "Open http://localhost:3001/api/docs"
##@ Quick Actions
quick-dev: ## Zero-config startup: dev containers + demo user
@npm run setup:dev:docker
quick-start: ## Legacy alias for quick-dev
@$(MAKE) quick-dev
@echo ""
@echo "📖 Next steps:"
@echo " - View logs: make logs"
@echo " - Stop services: make stop"
@echo " - Run tests: make test"
@echo " - View all commands: make help"
@echo ""
update: ## Update dependencies
@echo "📦 Updating dependencies..."
@cd backend && npm update
@cd frontend && npm update
@echo "✅ Dependencies updated!"
reset: clean setup start ## Complete reset - clean, setup, and start
@echo "✅ Stoic Budget has been reset!"