Metadata-Version: 2.4
Name: fastapi-file-routing
Version: 0.1.0
Summary: Nuxt/Nitro-style file-based routing for FastAPI
Keywords: fastapi,routing,file-based-routing,nuxt,nitro
Author: Oumar Barry
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Typing :: Typed
Requires-Dist: fastapi>=0.110
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/oumarbarry/fastapi-file-routing
Project-URL: Repository, https://github.com/oumarbarry/fastapi-file-routing
Project-URL: Issues, https://github.com/oumarbarry/fastapi-file-routing/issues
Project-URL: Changelog, https://github.com/oumarbarry/fastapi-file-routing/blob/main/CHANGELOG.md
Description-Content-Type: text/markdown

# fastapi-file-routing

[![CI](https://github.com/oumarbarry/fastapi-file-routing/actions/workflows/ci.yml/badge.svg)](https://github.com/oumarbarry/fastapi-file-routing/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/fastapi-file-routing.svg)](https://pypi.org/project/fastapi-file-routing/)

Nuxt/Nitro-style file-based routing for FastAPI. The layout of a `routes/`
directory becomes your URL structure; each file exposes plain `get`, `post`,
... functions.

```bash
uv add fastapi-file-routing   # or: pip install fastapi-file-routing
```

## Usage

```python
# main.py
from fastapi import FastAPI
from fastapi_file_routing import add_file_routes

app = FastAPI()
add_file_routes(app, "routes")
```

```
routes/
├── index.py           → /
├── users/
│   ├── index.py       → /users
│   ├── me.py          → /users/me
│   ├── {id}.py        → /users/{id}
│   └── {path...}.py   → /users/{path:path}   (catch-all)
└── _utils.py          → ignored ("_" prefix = private helper)
```

Each route file exposes module-level functions named after HTTP methods
(`get`, `post`, `put`, `patch`, `delete`, `head`, `options`), sync or async:

```python
# routes/users/{id}.py
async def get(id: int):
    return {"user": id}


def delete(id: int):
    return {"deleted": id}
```

These are ordinary FastAPI endpoint functions: typing, `Depends`,
response models and OpenAPI docs work as usual. Static routes are
registered before dynamic ones (`/users/me` wins over `/users/{id}`),
and `uvicorn main:app --reload` picks up route file changes out of the box.

> [!NOTE]
> Route files are loaded from their file path, not imported as a package:
> use absolute imports (`from myapp.db import ...`), not relative ones
> (`from .db import ...`). See [examples/basic](examples/basic) for a
> working layout.

## Middleware, auth and the rest

The library does one thing: map files to routes. Cross-cutting concerns
use FastAPI's own mechanisms:

- global middleware: `app.add_middleware(...)`
- per-route logic: `Depends(...)` in the handler signature
- per-tree config: `add_file_routes(app, "routes", prefix="/api", tags=["v1"], dependencies=[...])`
  (keyword arguments are forwarded to `include_router`)

## Errors at startup

`add_file_routes` raises before the app serves a single request when:

- the directory does not exist (`FileNotFoundError`)
- a route file defines no HTTP handler (`ValueError`)
- two files map to the same method and path, for example `users.py` and
  `users/index.py` (`ValueError`)

## Development

```bash
uv sync
uv run pytest
uv run ruff check . && uv run ruff format --check . && uv run ty check
```

See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

MIT
