diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..31b47d9b --- /dev/null +++ b/Makefile @@ -0,0 +1,232 @@ +# Voicebox Makefile +# Unix-only (macOS/Linux). Windows users should use WSL. + +SHELL := /bin/bash +.DEFAULT_GOAL := help + +# Directories +BACKEND_DIR := backend +TAURI_DIR := tauri +WEB_DIR := web +APP_DIR := app + +# Python +PYTHON := python3 +VENV := $(BACKEND_DIR)/venv +VENV_BIN := $(VENV)/bin +PIP := $(VENV_BIN)/pip +PYTHON_VENV := $(VENV_BIN)/python + +# Colors for output +BLUE := \033[0;34m +GREEN := \033[0;32m +YELLOW := \033[0;33m +NC := \033[0m # No Color + +.PHONY: help +help: ## Show this help message + @echo -e "$(BLUE)Voicebox$(NC) - Development Commands" + @echo "" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \ + awk 'BEGIN {FS = ":.*?## "}; {printf " $(GREEN)%-20s$(NC) %s\n", $$1, $$2}' + +# ============================================================================= +# SETUP +# ============================================================================= + +.PHONY: setup setup-js setup-python setup-rust + +setup: setup-js setup-python ## Full project setup (all dependencies) + @echo -e "$(GREEN)✓ Setup complete!$(NC)" + @echo -e " Run $(YELLOW)make dev$(NC) to start development servers" + +setup-js: ## Install JavaScript dependencies (bun) + @echo -e "$(BLUE)Installing JavaScript dependencies...$(NC)" + bun install + +setup-python: $(VENV)/bin/activate ## Set up Python virtual environment and dependencies + @echo -e "$(BLUE)Installing Python dependencies...$(NC)" + $(PIP) install --upgrade pip + $(PIP) install -r $(BACKEND_DIR)/requirements.txt + $(PIP) install git+https://github.com/QwenLM/Qwen3-TTS.git + @echo -e "$(GREEN)✓ Python environment ready$(NC)" + +$(VENV)/bin/activate: + @echo -e "$(BLUE)Creating Python virtual environment...$(NC)" + $(PYTHON) -m venv $(VENV) + +setup-rust: ## Install Rust toolchain (if not present) + @command -v rustc >/dev/null 2>&1 || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + +# ============================================================================= +# DEVELOPMENT +# ============================================================================= + +.PHONY: dev dev-backend dev-frontend dev-web kill-dev + +dev: ## Start backend + desktop app (parallel) + @echo -e "$(BLUE)Starting development servers...$(NC)" + @trap 'kill 0' EXIT; \ + $(MAKE) dev-backend & \ + sleep 2 && $(MAKE) dev-frontend & \ + wait + +dev-backend: ## Start FastAPI backend server + @echo -e "$(BLUE)Starting backend server on http://localhost:8000$(NC)" + cd $(BACKEND_DIR) && $(VENV_BIN)/uvicorn main:app --reload --port 8000 + +dev-frontend: ## Start Tauri desktop app + @echo -e "$(BLUE)Starting Tauri desktop app...$(NC)" + bun run dev + +dev-web: ## Start backend + web app (parallel) + @echo -e "$(BLUE)Starting web development servers...$(NC)" + @trap 'kill 0' EXIT; \ + $(MAKE) dev-backend & \ + sleep 2 && cd $(WEB_DIR) && bun run dev & \ + wait + +kill-dev: ## Kill all development processes + @echo -e "$(YELLOW)Killing development processes...$(NC)" + -pkill -f "uvicorn main:app" 2>/dev/null || true + -pkill -f "vite" 2>/dev/null || true + @echo -e "$(GREEN)✓ Processes killed$(NC)" + +# ============================================================================= +# BUILD +# ============================================================================= + +.PHONY: build build-server build-tauri build-web + +build: build-server build-tauri ## Build everything (server binary + desktop app) + @echo -e "$(GREEN)✓ Build complete!$(NC)" + +build-server: ## Build Python server binary + @echo -e "$(BLUE)Building server binary...$(NC)" + ./scripts/build-server.sh + +build-tauri: ## Build Tauri desktop app + @echo -e "$(BLUE)Building Tauri desktop app...$(NC)" + cd $(TAURI_DIR) && bun run tauri build + +build-web: ## Build web app + @echo -e "$(BLUE)Building web app...$(NC)" + cd $(WEB_DIR) && bun run build + @echo -e "$(GREEN)✓ Web build output in $(WEB_DIR)/dist/$(NC)" + +# ============================================================================= +# DATABASE & API +# ============================================================================= + +.PHONY: db-init db-reset generate-api + +db-init: ## Initialize SQLite database + @echo -e "$(BLUE)Initializing database...$(NC)" + cd $(BACKEND_DIR) && $(PYTHON_VENV) -c "from database import init_db; init_db()" + @echo -e "$(GREEN)✓ Database created at $(BACKEND_DIR)/data/voicebox.db$(NC)" + +db-reset: ## Reset database (delete and reinitialize) + @echo -e "$(YELLOW)Resetting database...$(NC)" + rm -f $(BACKEND_DIR)/data/voicebox.db + $(MAKE) db-init + +generate-api: ## Generate TypeScript API client from OpenAPI schema + @echo -e "$(BLUE)Generating API client...$(NC)" + @echo -e "$(YELLOW)Note: Backend must be running (make dev-backend)$(NC)" + ./scripts/generate-api.sh + @echo -e "$(GREEN)✓ API client generated in $(APP_DIR)/src/lib/api/$(NC)" + +# ============================================================================= +# CODE QUALITY +# ============================================================================= + +.PHONY: lint format typecheck check + +lint: ## Run linter (Biome) + @echo -e "$(BLUE)Linting...$(NC)" + bun run lint + +format: ## Format code (Biome) + @echo -e "$(BLUE)Formatting...$(NC)" + bun run format + +typecheck: ## Run TypeScript type checking + @echo -e "$(BLUE)Type checking...$(NC)" + bun run tsc --noEmit + +check: ## Run all checks (Biome lint + format + type check) + @echo -e "$(BLUE)Running all checks...$(NC)" + bun run check + @echo -e "$(GREEN)✓ All checks passed$(NC)" + +# ============================================================================= +# TESTING +# ============================================================================= + +.PHONY: test test-backend test-frontend + +test: test-backend test-frontend ## Run all tests + @echo -e "$(GREEN)✓ All tests passed$(NC)" + +test-backend: ## Run Python backend tests (requires pytest) + @echo -e "$(BLUE)Running backend tests...$(NC)" + @if [ -f "$(VENV_BIN)/pytest" ]; then \ + cd $(BACKEND_DIR) && $(VENV_BIN)/pytest -v; \ + else \ + echo -e "$(YELLOW)pytest not installed. Run: $(PIP) install pytest$(NC)"; \ + fi + +test-frontend: ## Run frontend tests (requires test script in package.json) + @echo -e "$(BLUE)Running frontend tests...$(NC)" + @if bun run test --help >/dev/null 2>&1; then \ + bun run test; \ + else \ + echo -e "$(YELLOW)No test script configured$(NC)"; \ + fi + +# ============================================================================= +# LOGS & DEBUGGING +# ============================================================================= + +.PHONY: logs docs + +logs: ## Tail backend logs + @echo -e "$(BLUE)Tailing logs (Ctrl+C to stop)...$(NC)" + tail -f $(BACKEND_DIR)/logs/*.log 2>/dev/null || echo "No log files found" + +docs: ## Open API documentation (backend must be running) + @echo -e "$(BLUE)Opening API docs...$(NC)" + open http://localhost:8000/docs 2>/dev/null || xdg-open http://localhost:8000/docs + +# ============================================================================= +# CLEAN +# ============================================================================= + +.PHONY: clean clean-python clean-build clean-all + +clean: ## Clean build artifacts + @echo -e "$(BLUE)Cleaning build artifacts...$(NC)" + rm -rf $(TAURI_DIR)/src-tauri/target/release + rm -rf $(WEB_DIR)/dist + rm -rf $(APP_DIR)/dist + @echo -e "$(GREEN)✓ Build artifacts cleaned$(NC)" + +clean-python: ## Clean Python cache and virtual environment + @echo -e "$(BLUE)Cleaning Python files...$(NC)" + rm -rf $(VENV) + find $(BACKEND_DIR) -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true + find $(BACKEND_DIR) -type f -name "*.pyc" -delete 2>/dev/null || true + @echo -e "$(GREEN)✓ Python environment cleaned$(NC)" + +clean-build: ## Clean Rust/Tauri build cache + @echo -e "$(BLUE)Cleaning Rust build cache...$(NC)" + cd $(TAURI_DIR)/src-tauri && cargo clean + @echo -e "$(GREEN)✓ Rust cache cleaned$(NC)" + +clean-all: clean clean-python clean-build ## Nuclear clean (everything) + @echo -e "$(BLUE)Cleaning node_modules...$(NC)" + rm -rf node_modules + rm -rf $(APP_DIR)/node_modules + rm -rf $(TAURI_DIR)/node_modules + rm -rf $(WEB_DIR)/node_modules + @echo -e "$(GREEN)✓ Full clean complete$(NC)"