Metadata-Version: 2.4
Name: fastvia-kit
Version: 0.1.0
Summary: Production-ready FastAPI backend toolkit with auth, DB, migrations, Redis, ARQ jobs, middleware, logging, pagination, rate limiting, and security helpers.
Project-URL: Homepage, https://gitlab.com/abdulfatahbabakrkhail/fastvia
Project-URL: Repository, https://gitlab.com/abdulfatahbabakrkhail/fastvia
Project-URL: Issues, https://gitlab.com/abdulfatahbabakrkhail/fastvia/-/issues
Author-email: Abdul Fatah Babakrkhail <fatahbabakrkhail@gmail.com>
Maintainer-email: Abdul Fatah Babakrkhail <fatahbabakrkhail@gmail.com>
License: MIT
License-File: LICENSE
Keywords: alembic,api,arq,asyncpg,auth,authentication,backend,fastapi,logging,middleware,pagination,rate-limit,redis,saas,security,sqlalchemy
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: alembic>=1.17.1
Requires-Dist: argon2-cffi>=23.1.0
Requires-Dist: arq<0.29.0,>=0.26.3
Requires-Dist: asyncpg>=0.30.0
Requires-Dist: email-validator>=2.3.0
Requires-Dist: fastapi-users-db-sqlalchemy<8.0.0,>=7.0.0
Requires-Dist: fastapi-users<16.0.0,>=15.0.0
Requires-Dist: fastapi>=0.120.0
Requires-Dist: limits>=5.6.0
Requires-Dist: pydantic-settings>=2.11.0
Requires-Dist: pydantic>=2.12.0
Requires-Dist: python-jose>=3.5.0
Requires-Dist: redis<6.0.0,>=5.0.0
Requires-Dist: slowapi>=0.1.9
Requires-Dist: sqlalchemy>=2.0.44
Requires-Dist: starlette>=0.49.0
Provides-Extra: dev
Requires-Dist: aiosqlite>=0.20.0; extra == 'dev'
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: httpx>=0.28.0; extra == 'dev'
Requires-Dist: mypy>=1.10.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Requires-Dist: uvicorn>=0.38.0; extra == 'dev'
Description-Content-Type: text/markdown

# Fastvia

Production-ready FastAPI backend toolkit with auth, DB, migrations, Redis, ARQ jobs, middleware, logging, pagination, rate limiting, and security helpers.

Fastvia does **not** take over your application.  
You still create your own FastAPI app, routers, lifespan, database models, and business logic. Fastvia gives you clean reusable building blocks for the parts most production APIs need.

> The PyPI distribution name is `fastvia-kit`, while the Python import package is `fastvia`.

## Installation

```bash
pip install fastvia-kit
```

For development:

```bash
make install-dev
```

## What Fastvia Provides

- Request context middleware with request ID and process time
- Security headers middleware
- Logging context with text and JSON formatters
- API error classes and exception handlers
- Pagination helpers
- Redis-backed rate limiting with SlowAPI
- Async SQLAlchemy database helpers
- Redis client helpers
- ARQ job helpers
- JWT/FastAPI Users auth helpers
- Alembic migration helpers
- Bootstrap helper for existing FastAPI apps

## Quick Start

You create your FastAPI app normally:

```python
from fastapi import FastAPI

from fastvia import bootstrap_fastvia

app = FastAPI(
    title="My API",
    version="1.0.0",
)

bootstrap_fastvia(
    app,
    logger_name="myapi",
    log_format="json",
    cors_origins=["http://localhost:3000"],
    rate_limit_storage_uri="redis://localhost:6379/0",
)
```

This can configure:

- logging
- request context middleware
- security headers
- error handlers
- CORS
- GZip
- rate limiting

## Example

A small runnable FastAPI example is available in:

```text
examples/basic_app.py
```

Install development dependencies first:

```bash
make install-dev
```

Run the example app:

```bash
uvicorn examples.basic_app:app --reload
```

Then open:

```text
http://127.0.0.1:8000/docs
```

The example shows:

- Fastvia bootstrap setup
- request context headers
- security headers
- pagination
- API errors
- rate limiting

## Request Context Middleware

```python
from fastapi import FastAPI

from fastvia.middleware import RequestContextMiddleware

app = FastAPI()
app.add_middleware(RequestContextMiddleware)
```

Each response includes:

```text
x-request-id
x-process-time
```

The request context is also connected to Fastvia logging.

## Security Headers Middleware

```python
from fastvia.middleware import SecurityHeadersMiddleware

app.add_middleware(
    SecurityHeadersMiddleware,
    enable_hsts=True,
)
```

By default, Fastvia adds common security headers such as:

- `X-Content-Type-Options`
- `X-Frame-Options`
- `Referrer-Policy`
- `Permissions-Policy`
- `Cache-Control`
- `Content-Security-Policy`

You can customize or disable values when needed.

## Logging

```python
from fastvia.logging import setup_logging, log_extra

logger = setup_logging(
    level="INFO",
    log_format="json",
    logger_name="myapi",
)

logger.info(
    "Event processed",
    extra=log_extra(
        event_id="evt_123",
        event_type="demo.event.success",
    ),
)
```

Fastvia supports request-scoped log context:

```text
request_id
method
path
event_id
event_type
```

## API Errors

```python
from fastapi import FastAPI

from fastvia.errors import NotFoundError, register_exception_handlers
from fastvia.middleware import RequestContextMiddleware

app = FastAPI()
app.add_middleware(RequestContextMiddleware)
register_exception_handlers(app)


@app.get("/items/{item_id}")
async def get_item(item_id: int):
    raise NotFoundError("Item not found.")
```

Example response:

```json
{
  "error": "not_found",
  "message": "Item not found.",
  "details": {},
  "request_id": "..."
}
```

## Pagination

```python
from fastapi import Depends
from pydantic import BaseModel

from fastvia.pagination import (
    PageMeta,
    PaginatedResponse,
    PaginationParams,
    pagination_params,
)


class ItemOut(BaseModel):
    id: int
    name: str


@app.get("/items", response_model=PaginatedResponse[ItemOut])
async def list_items(
    pagination: PaginationParams = Depends(pagination_params),
):
    rows = [
        ItemOut(id=1, name="First"),
        ItemOut(id=2, name="Second"),
    ]
    total = 2

    meta = PageMeta.from_pagination(
        total=total,
        pagination=pagination,
    )

    return PaginatedResponse(
        items=rows,
        meta=meta,
    )
```

Response shape:

```json
{
  "items": [],
  "meta": {
    "total": 42,
    "page": 2,
    "per_page": 10,
    "pages": 5,
    "has_next": true,
    "has_prev": true
  }
}
```

## Rate Limiting

```python
from fastapi import Request

from fastvia.rate_limit import register_rate_limiting

limiter = register_rate_limiting(
    app,
    storage_uri="redis://localhost:6379/0",
    default_limits=[],
)


@app.get("/ping")
@limiter.limit("10/minute")
async def ping(request: Request):
    return {"message": "pong"}
```

For authenticated user-based keys:

```python
from fastvia.auth import get_user_id_from_bearer_token
from fastvia.rate_limit import user_or_ip_key

key_func = user_or_ip_key(
    user_id_resolver=lambda request: get_user_id_from_bearer_token(
        request,
        secret="secret",
        algorithm="HS256",
    )
)

limiter = register_rate_limiting(
    app,
    storage_uri="redis://localhost:6379/0",
    key_func=key_func,
)
```

## Database Helpers

```python
from fastvia.db import (
    create_async_db_engine,
    create_session_dependency,
    create_session_factory,
)

engine = create_async_db_engine(
    "postgresql+asyncpg://user:password@localhost/db",
)

SessionLocal = create_session_factory(engine)

get_db = create_session_dependency(SessionLocal)
```

Then use it in routes:

```python
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession


@app.get("/items")
async def list_items(db: AsyncSession = Depends(get_db)):
    ...
```

## Redis Helper

```python
from fastvia.redis import close_all_redis, get_redis

redis = get_redis("redis://localhost:6379/0")

await redis.set("key", "value")
```

Close clients during shutdown:

```python
await close_all_redis()
```

## ARQ Helpers

```python
from fastvia.jobs import create_arq_pool

arq_pool = await create_arq_pool("redis://localhost:6379/0")
```

Fastvia also provides JSON job serializer/deserializer helpers.

## Auth Helpers

Fastvia provides helpers for FastAPI Users JWT auth setup:

```python
from fastvia.auth import create_jwt_auth_backend

auth_backend = create_jwt_auth_backend(
    secret="secret",
    lifetime_seconds=3600,
    algorithm="HS256",
    token_url="/auth/login",
)
```

It also provides helpers for wiring FastAPI Users dependencies while keeping your app-specific `UserManager`, email verification, reset password, and user model inside your own project.

## Alembic Migration Helpers

```python
from fastvia.migrations import create_alembic_config, upgrade_to_head

config = create_alembic_config(
    config_path="alembic.ini",
    database_url="postgresql+asyncpg://user:password@localhost/db",
)

upgrade_to_head(config)
```

Fastvia does not run migrations automatically.  
Migrations should be explicit, especially in production.

## Development

Install development dependencies:

```bash
make install-dev
```

Run tests:

```bash
make test
```

Run tests with coverage:

```bash
make test-cov
```

Format code:

```bash
make format
```

Lint code:

```bash
make lint
```

Clean build and cache files:

```bash
make clean
```

Build package:

```bash
make build
```

Check package:

```bash
make check
```

Equivalent raw commands:

```bash
pip install -e ".[dev]"
pytest
pytest --cov=fastvia --cov-report=term-missing
ruff format .
ruff check . --fix
python -m build
twine check dist/*
```

## License

MIT