# {{display_name}}

FastAPI application generated by BoringPy.

## Features

- ✅ **Modern FastAPI** with lifespan management
- ✅ **SQLModel database** with migrations (Alembic)
- ✅ **Docker support** with multi-stage builds
- ✅ **Loguru integration** with request tracing
- ✅ **Type safety** with full type annotations
- ✅ **Pydantic Settings** for configuration
- ✅ **Makefile commands** for common tasks
- ✅ **Health checks** for monitoring
- ✅ **Test suite** with pytest

## Tech Stack

- **Framework**: FastAPI {{version}}
- **Database**: {{db_type}} (configurable)
- **ORM**: SQLModel
- **Migrations**: Alembic
- **Logging**: Loguru
- **Testing**: pytest
- **Linting**: ruff
- **Type checking**: ty
- **Container**: Docker + docker-compose

## Project Structure

```
{{package_name}}/
├── app/                    # Application code
│   ├── core/              # Core configuration
│   │   ├── config.py      # Settings
│   │   ├── database.py    # Database setup
│   │   ├── logger.py      # Logging setup
│   │   └── lifespan.py    # App lifespan
│   ├── api/               # API routes
│   │   └── v1/            # API version 1
│   │       └── endpoints/ # Endpoints
│   ├── models/            # SQLModel models
│   ├── services/          # Business logic
│   └── main.py            # Entry point
├── migrations/            # Alembic migrations
│   ├── env.py            # Migration environment
│   └── versions/         # Migration files
├── tests/                 # Test suite
├── Dockerfile            # Multi-stage Docker build
├── docker-compose.yml    # Container orchestration
├── Makefile              # Development commands
├── alembic.ini           # Migration config
├── .env.example          # Environment template
└── pyproject.toml        # Dependencies
```

## Quick Start

### 🐳 Using Docker (Recommended)

```bash
# 1. Setup environment
cp .env.example .env

# 2. Start services (API + Database)
make docker-up

# 3. Run database migrations
make db-upgrade

# 4. Access the API
open http://localhost:{{port}}/docs
```

View logs:
```bash
make docker-logs
```

Stop containers:
```bash
make docker-down
```

### 💻 Local Development

```bash
# 1. Setup environment
cp .env.example .env

# 2. Install dependencies
make install

# 3. Start database (if using PostgreSQL/MySQL)
make docker-up  # Only starts DB, not API

# 4. Run migrations
make db-upgrade

# 5. Start API
make dev
```

## Available Commands

Run `make help` to see all available commands:

### Quality Checks
- `make format` - Format code with ruff
- `make lint` - Lint code
- `make type` - Type check
- `make check` - Run all checks

### Docker
- `make docker-build` - Build Docker image
- `make docker-up` - Start containers
- `make docker-down` - Stop containers
- `make docker-logs` - View logs
- `make docker-shell` - Open shell in container

### Database & Migrations
- `make db-create-migration MSG="..."` - Create new migration
- `make db-upgrade` - Apply pending migrations
- `make db-downgrade` - Rollback last migration
- `make db-history` - View migration history
- `make db-current` - Show current revision

### Testing
- `make test` - Run tests
- `make test-cov` - Run tests with coverage

### Development
- `make dev` - Run API locally
- `make clean` - Clean cache files

## Database Migrations

This project uses Alembic for database migrations.

### Create a new migration

```bash
make db-create-migration MSG="add users table"
```

This creates a new migration file in `migrations/versions/`.

### Edit the migration

```python
# migrations/versions/20240116_1234_add_users_table.py
def upgrade() -> None:
    """Apply migration changes."""
    op.create_table(
        'users',
        sa.Column('id', sa.Integer(), primary_key=True),
        sa.Column('email', sa.String(255), unique=True),
        sa.Column('name', sa.String(255)),
    )

def downgrade() -> None:
    """Revert migration changes."""
    op.drop_table('users')
```

### Apply migrations

```bash
# Apply all pending migrations
make db-upgrade

# Rollback last migration
make db-downgrade

# View migration history
make db-history
```

## API Access

Once running, access:

- **API Docs (Swagger)**: http://localhost:{{port}}/docs
- **ReDoc**: http://localhost:{{port}}/redoc
- **OpenAPI JSON**: http://localhost:{{port}}/openapi.json
- **Health Check**: http://localhost:{{port}}/api/v1/health

## Configuration

Configuration is managed through Pydantic Settings in `app/core/config.py`.

Settings can be configured via:
1. Environment variables
2. `.env` file
3. Default values in code

### Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `APP_NAME` | "{{display_name}}" | Application name |
| `ENVIRONMENT` | development | Environment |
| `DEBUG` | True | Enable debug mode |
| `LOG_LEVEL` | INFO | Logging level |
| `HOST` | 0.0.0.0 | Server host |
| `PORT` | {{port}} | Server port |
| `DATABASE_URL` | See .env.example | Database connection |
| `DB_ECHO` | False | Log SQL queries |

## Development Workflow

### 1. Create a new model

```python
# app/models/user.py
from sqlmodel import Field, SQLModel

class User(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    email: str = Field(unique=True, index=True)
    name: str
```

### 2. Create migration

```bash
make db-create-migration MSG="add users table"
```

### 3. Apply migration

```bash
make db-upgrade
```

### 4. Create endpoint

```python
# app/api/v1/endpoints/users.py
from fastapi import APIRouter, Depends
from sqlmodel import Session, select
from app.core.database import get_session
from app.models.user import User

router = APIRouter()

@router.get("/users")
async def list_users(session: Session = Depends(get_session)):
    users = session.exec(select(User)).all()
    return users
```

### 5. Register router

```python
# app/main.py
from app.api.v1.endpoints import users

app.include_router(
    users.router,
    prefix=settings.api_v1_prefix,
    tags=["users"],
)
```

### 6. Test

```bash
make test
```

## Testing

```bash
# Run all tests
make test

# Run with coverage
make test-cov

# Run specific test
uv run pytest tests/test_api.py::test_health_check -v
```

## Deployment

### Using Docker

1. Build production image:
   ```bash
   docker build -t {{package_name}}:latest .
   ```

2. Run container:
   ```bash
   docker run -p {{port}}:{{port}} \
     -e DATABASE_URL=postgresql://... \
     -e ENVIRONMENT=production \
     {{package_name}}:latest
   ```

### Cloud Platforms

Customize `make deploy` target for your platform:

- **AWS ECS**: `aws ecs update-service ...`
- **GCP Cloud Run**: `gcloud run deploy {{package_name}} --source .`
- **Azure**: `az containerapp update ...`
- **Heroku**: `git push heroku main`
- **Railway**: `railway up`
- **Fly.io**: `fly deploy`

## Logging

The application uses Loguru for structured logging with trace IDs:

```python
from app.core.logger import log

log.info("Processing user", user_id=123)
log.error("Failed to save", error=str(e))
log.debug("Debug information")
```

Every request gets a unique trace ID included in:
- All log messages
- Response headers as `X-Trace-ID`
- Error responses

## Troubleshooting

### Database connection issues

```bash
# Check database is running
make docker-ps

# View database logs
docker-compose logs postgres  # or mysql

# Test connection
uv run python -c "from app.core.database import engine; print(engine)"
```

### Migration issues

```bash
# Check current revision
make db-current

# View migration history
make db-history

# Reset database (WARNING: destroys data)
make db-reset
```

## Generated by BoringPy

This project was generated using [BoringPy](https://github.com/yourusername/boringpy) - A modern Python scaffolding framework.

