Metadata-Version: 2.4
Name: fanest
Version: 0.3.0b3
Summary: NestJS-style backend architecture for Python, powered by FastAPI.
Project-URL: Homepage, https://github.com/ahfoysal/fanest
Project-URL: Repository, https://github.com/ahfoysal/fanest
Project-URL: Issues, https://github.com/ahfoysal/fanest/issues
License-Expression: MIT
License-File: LICENSE
Keywords: backend,dependency-injection,fastapi,framework,nestjs,python
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.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: aiosqlite>=0.20.0
Requires-Dist: croniter>=3.0.0
Requires-Dist: email-validator>=2.2.0
Requires-Dist: fastapi>=0.115.0
Requires-Dist: graphql-core>=3.2.3
Requires-Dist: greenlet>=3.0.0
Requires-Dist: httpx2>=2.5.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pyjwt>=2.8.0
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: sqlalchemy>=2.0.0
Requires-Dist: typer>=0.12.0
Requires-Dist: uvicorn>=0.30.0
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: pyright>=1.1.411; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Requires-Dist: tomli>=2.0.0; (python_version < '3.11') and extra == 'dev'
Requires-Dist: twine>=6.0.0; extra == 'dev'
Provides-Extra: grpc
Requires-Dist: grpcio-tools>=1.64.0; extra == 'grpc'
Requires-Dist: grpcio>=1.64.0; extra == 'grpc'
Provides-Extra: integrations
Requires-Dist: aio-pika>=9.4.0; extra == 'integrations'
Requires-Dist: aiokafka>=0.10.0; extra == 'integrations'
Requires-Dist: asyncpg>=0.29.0; extra == 'integrations'
Requires-Dist: motor>=3.0.0; extra == 'integrations'
Requires-Dist: nats-py>=2.7.0; extra == 'integrations'
Requires-Dist: redis>=5.0.0; extra == 'integrations'
Provides-Extra: kafka
Requires-Dist: aiokafka>=0.10.0; extra == 'kafka'
Provides-Extra: microservices
Requires-Dist: aio-pika>=9.4.0; extra == 'microservices'
Requires-Dist: aiokafka>=0.10.0; extra == 'microservices'
Requires-Dist: nats-py>=2.7.0; extra == 'microservices'
Requires-Dist: redis>=5.0.0; extra == 'microservices'
Provides-Extra: mongo
Requires-Dist: motor>=3.0.0; extra == 'mongo'
Provides-Extra: nats
Requires-Dist: nats-py>=2.7.0; extra == 'nats'
Provides-Extra: postgres
Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
Provides-Extra: rabbitmq
Requires-Dist: aio-pika>=9.4.0; extra == 'rabbitmq'
Provides-Extra: redis
Requires-Dist: redis>=5.0.0; extra == 'redis'
Provides-Extra: standard
Requires-Dist: uvicorn[standard]>=0.30.0; extra == 'standard'
Description-Content-Type: text/markdown

# FaNest

A progressive Python framework for building structured, scalable, and maintainable backend applications.

FaNest brings the NestJS way of thinking to Python: modules, controllers, services, decorators, dependency injection, guards, pipes, interceptors, filters, gateways, scheduled jobs, and package-style integrations. FastAPI does the HTTP work underneath; FaNest gives the application an architecture.

It is built for developers who like the NestJS workflow but want to work in Python.

## Description

Python has excellent web libraries, but larger applications still need a repeatable structure. FaNest provides that structure without hiding the Python ecosystem.

The framework combines:

- class-based modules, controllers, services, and gateways
- constructor-based dependency injection
- decorator-driven routing and WebSocket messages
- request pipeline layers: guards, pipes, interceptors, and filters
- FastAPI, Pydantic, SQLAlchemy, and pytest-friendly defaults
- a CLI shaped around everyday backend work

FaNest is inspired by NestJS, but it is not a wrapper around NestJS and is not affiliated with the NestJS project.

## Philosophy

The goal is not to make Python pretend to be TypeScript. The goal is to keep the workflow familiar for NestJS developers while choosing Python-native tools where they fit better.

FaNest should feel predictable in a growing codebase:

- modules describe boundaries
- providers hold business logic
- controllers stay thin
- decorators make framework behavior visible
- tests can override dependencies without patching imports
- packages can plug into the same module system

Small APIs should stay small. Bigger APIs should not become a pile of unrelated route functions.

## Getting Started

Install FaNest from PyPI:

```bash
pip install fanest
```

That installs the framework, FastAPI, Uvicorn, Pydantic, Typer, SQLAlchemy, and the core runtime dependencies.

For the recommended server extras, use:

```bash
pip install "fanest[standard]"
```

Create and run a new app:

```bash
fanest new blog-api
cd blog-api
fanest dev main.py
```

Open:

```txt
http://127.0.0.1:8000/docs
```

For an existing app:

```bash
fanest dev main.py
fanest run main.py
```

For local framework development:

```bash
uv sync --extra dev
uv run fanest dev examples/basic/main.py
```

Then open:

```txt
http://127.0.0.1:8000/docs
```

## A Small Application

```python
from pydantic import BaseModel

from fanest import Body, Controller, FaNestFactory, Get, Injectable, Module, Post


class CreateUserDto(BaseModel):
    name: str


@Injectable()
class UsersService:
    def __init__(self):
        self.users = []

    def find_all(self):
        return self.users

    def create(self, dto: CreateUserDto):
        user = {"id": len(self.users) + 1, "name": dto.name}
        self.users.append(user)
        return user


@Controller("users")
class UsersController:
    def __init__(self, users_service: UsersService):
        self.users_service = users_service

    @Get("/")
    async def find_all(self):
        return self.users_service.find_all()

    @Post("/")
    async def create(self, dto: CreateUserDto = Body()):
        return self.users_service.create(dto)


@Module(controllers=[UsersController], providers=[UsersService])
class AppModule:
    pass


app = FaNestFactory.create(AppModule)
```

## All Uses Example

The fuller example lives in [examples/all_uses/main.py](/Users/foysal/fanest/examples/all_uses/main.py).

It shows:

- REST controllers
- Pydantic DTOs
- mapped DTO helpers
- constructor injection
- custom provider tokens
- middleware
- file uploads
- file validation pipes
- response headers, SSE, and streaming files
- rendered templates and static assets
- session cookies and security headers
- custom parameter decorators
- config module
- config validation helpers
- async module configuration
- i18n translations and locale extraction
- JWT auth
- Passport-style auth strategies
- role guards
- cache interceptor
- cache stores
- throttling guard
- Swagger document setup, security schemes, and TypeScript client generation
- typed exception filters
- Reflector and discovery services
- health indicators
- disk and memory health checks
- metrics counters
- worker task handlers
- GraphQL resolvers and subscriptions
- health endpoint
- SQLAlchemy module wiring
- TypeORM-style repository injection over SQLAlchemy
- Mongo-style document collections
- Mongoose-style module aliases
- interval jobs
- cron jobs
- timeout jobs and scheduler registry
- queue processors
- Bull-style queue aliases
- mailer service
- CQRS command/query/event buses
- event emitter wildcard, once, and off helpers
- named microservice transports
- WebSocket gateway with rooms, broadcasting, guards, pipes, filters, message-body decorators, connected-socket decorators, and Socket.IO-style emitters
- global prefix, CORS, and global pipes
- `APP_GUARD`, `APP_PIPE`, `APP_INTERCEPTOR`, and `APP_FILTER` global providers

Run it:

```bash
uv run uvicorn examples.all_uses.main:app --reload
```

Useful paths:

```txt
GET  /api/users
POST /api/users
POST /api/users/login
GET  /api/admin/me
GET  /api/health
GET  /api/docs
WS   /api/chat
```

## CLI

```bash
fanest new blog-api
fanest workspace acme-platform
fanest start main:app --reload
fanest dev main.py
fanest run main.py
fanest run src/main.py --app application --workers 2

fanest generate resource users
fanest generate module users
fanest generate controller users
fanest generate service users
fanest generate guard auth
fanest generate pipe validation
fanest generate interceptor logging
fanest generate filter http_error
fanest generate gateway chat
fanest generate dto users
fanest generate middleware request_id
fanest generate decorator current_user
fanest generate library common
fanest generate resource users --dry-run
fanest generate module users --module app_module.py
```

## Core Features

FaNest currently includes:

- `@Module`
- `@Controller`
- `@Injectable`
- `@Get`, `@Post`, `@Put`, `@Patch`, `@Delete`, `@Options`, `@Head`, `@All`
- `Body`, `Param`, `Query`, `Header`, `Headers`, `Cookie`, `Req`, `Res`, `Ip`, `HostParam`, `Session`
- `UploadedFile`, `UploadedFiles`, `BackgroundTasks`, custom param decorators
- `HttpCode`, `Redirect`, `SetHeader`, `SetMetadata`, `Version`, `ResponseModel`
- `Sse` and `StreamableFile`
- `UseGuards`
- `UsePipes`
- `UseInterceptors`
- `UseFilters`
- `WebSocketGateway`
- `SubscribeMessage`
- `MessageBody`
- `ConnectedSocket`
- `Interval`
- `Cron`
- `Timeout`
- `Global`
- `MessagePattern`
- `EventPattern`
- lifecycle hooks: `on_module_init`, `on_application_shutdown`

## Dependency Injection

FaNest supports class providers and Nest-style provider definitions:

```python
from fanest import Inject, Injectable, Module, token, use_factory, use_value

CONFIG = token("CONFIG")
MESSAGE = token("MESSAGE")


@Injectable()
class MessageService:
    def __init__(self, message: str = Inject(MESSAGE)):
        self.message = message


@Module(
    providers=[
        MessageService,
        use_value(CONFIG, {"message": "hello"}),
        use_factory(MESSAGE, lambda config: config["message"], inject=[CONFIG]),
    ],
)
class MessageModule:
    pass
```

Supported provider types:

- class providers
- value providers
- factory providers
- async factory providers
- existing provider aliases
- injection tokens
- optional injection
- singleton, request, and transient scopes
- `forward_ref`
- global modules
- provider overrides in tests

## Packages

The repository already contains first-party package starts:

```txt
fanest.core              modules, DI, scanner, app factory
fanest.common            decorators, exceptions, pipes
fanest.platform_fastapi  FastAPI adapter
fanest.session           signed cookie sessions
fanest.security          helmet-style security headers
fanest.i18n              translations and I18nLang helper
fanest.config            ConfigModule and ConfigService
fanest.swagger           decorators, DocumentBuilder, SwaggerModule
fanest.auth              JWT service, passport strategies, auth guard, roles guard
fanest.sqlalchemy        async SQLAlchemy module, repositories, TypeOrmModule alias
fanest.mongodb           Mongo/Mongoose-style document service and collections
fanest.cache             cache service, interceptor, and store adapters
fanest.throttler         throttling module and guard
fanest.schedule          interval, cron, timeout jobs, scheduler registry
fanest.websockets        connection manager, rooms, broadcasting, Socket.IO-style server
fanest.serve_static      static asset module
fanest.queues            QueueModule/BullModule, processors, jobs
fanest.mailer            mail service with outbox and SMTP handoff
fanest.cqrs              command, query, and event buses
fanest.events            event emitter and OnEvent decorators
fanest.graphql           resolvers, queries, mutations, subscriptions, GraphQL endpoint
fanest.microservices     message/event patterns and named transports
fanest.mapped_types      PartialType, PickType, OmitType, IntersectionType
fanest.health            health endpoint module with reusable indicators
fanest.metrics           counters and metrics endpoint
fanest.workers           task handler registry
fanest.discovery/core    Reflector and DiscoveryService
fanest.testing           TestingModule and provider overrides
```

## Built-In Pipes And Exceptions

Pipes:

- `ValidationPipe`
- `ParseIntPipe`
- `ParseBoolPipe`
- `ParseFloatPipe`
- `ParseUUIDPipe`
- `ParseEnumPipe`
- `ParseArrayPipe`
- `DefaultValuePipe`
- `ParseFilePipe`
- `MaxFileSizeValidator`
- `FileTypeValidator`

Exceptions:

- `BadRequestException`
- `UnauthorizedException`
- `ForbiddenException`
- `NotFoundException`
- `ConflictException`
- `InternalServerErrorException`
- `UnprocessableEntityException`
- `TooManyRequestsException`
- `ServiceUnavailableException`

## Swagger

```python
from fanest.swagger import DocumentBuilder, SwaggerModule

config = (
    DocumentBuilder()
    .set_title("Blog API")
    .set_description("A FaNest application")
    .set_version("1.0.0")
    .add_bearer_auth()
    .build()
)

document = SwaggerModule.create_document(app, config)
SwaggerModule.setup("/docs", app, document)
```

Swagger decorators include `ApiTags`, `ApiOperation`, `ApiParam`, `ApiQuery`, `ApiHeader`,
`ApiBody`, `ApiResponse`, `ApiConsumes`, `ApiProduces`, `ApiBearerAuth`, `ApiBasicAuth`,
`ApiCookieAuth`, `ApiSecurity`, `ApiExtraModels`, `ApiExtension`, response shortcuts such as
`ApiOkResponse`, `ApiCreatedResponse`, `ApiNotFoundResponse`, `ApiExcludeEndpoint`,
`ApiProperty`, `ApiPropertyOptional`, and `ApiHideProperty`.
`SwaggerModule.generate_typescript_client(document)` can emit a small fetch client from the
generated OpenAPI document.

## WebSockets

```python
from fanest import ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway


@WebSocketGateway("/chat")
class ChatGateway:
    @SubscribeMessage("rename")
    async def rename(self, name: str = MessageBody("name"), socket=ConnectedSocket()):
        return {"name": name}
```

Gateways can use guards, pipes, filters, rooms, broadcast helpers, and `SocketIoServer` for
the familiar `server.to("room").emit(...)` shape.

## Health Checks

```python
from fanest.health import DiskHealthIndicator, HealthIndicator, HealthModule, MemoryHealthIndicator


HealthModule.register(
    [
        HealthIndicator("database", lambda: {"status": "ok"}),
        DiskHealthIndicator(path="/"),
        MemoryHealthIndicator(rss_threshold_mb=512),
    ]
)
```

## Mapped Types

```python
from fanest import PartialType, PickType

UpdateUserDto = PartialType(CreateUserDto)
PublicUserDto = PickType(UserDto, ["id", "name"])
```

## ORM

FaNest ships with an async SQLAlchemy package and Nest-style repository injection:

```python
from fanest import Injectable, Module
from fanest.sqlalchemy import InjectRepository, SqlAlchemyRepository, TypeOrmModule


@Injectable()
class UsersService:
    def __init__(self, users: SqlAlchemyRepository = InjectRepository(User)):
        self.users = users


@Module(
    imports=[
        TypeOrmModule.for_root(database_url="sqlite+aiosqlite:///app.db"),
        TypeOrmModule.for_feature([User]),
    ],
    providers=[UsersService],
)
class UsersModule:
    pass
```

Repositories include `find_all`, `find_by`, `find_one`, `find_one_by`, `count`, `save`,
`update`, `delete`, and `delete_by`. `SqlAlchemyModule` and `TypeOrmModule` point to the same
Python-native SQLAlchemy integration, so Nest users can keep the familiar module shape while
still using SQLAlchemy models.

## Middleware

```python
class RequestIdMiddleware:
    async def use(self, request, call_next):
        response = await call_next(request)
        response.headers["x-request-id"] = "local"
        return response


@Module(controllers=[UsersController], middlewares=[RequestIdMiddleware])
class AppModule:
    pass
```

Modules can also expose a Nest-style `configure(consumer)` method for route-scoped
middleware with exclusions:

```python
class AppModule:
    def configure(self, consumer):
        consumer.apply(RequestIdMiddleware).exclude("/health").for_routes("/users*")
```

## Microservices

```python
from fanest.microservices import MessagePattern, MicroserviceServer


class MathService:
    @MessagePattern("math.double")
    async def double(self, data, context):
        return data * 2


server = MicroserviceServer(AppModule).compile()
client = server.client()
result = await client.send("math.double", 21)
```

## Testing

```python
from fanest.testing import TestingModule

app = (
    TestingModule.create(AppModule)
    .override_provider(UsersService, MockUsersService())
    .compile()
)
```

Run the test suite:

```bash
uv run pytest
uv run ruff check .
```

## NestJS Parity

FaNest is aiming at the full NestJS surface area. The current implementation covers the core application model and many common packages, but some large systems still need deeper work.

Current:

- modules, controllers, providers
- DI with custom, async, scoped, optional, and aliased providers
- `APP_GUARD`, `APP_PIPE`, `APP_INTERCEPTOR`, and `APP_FILTER` global enhancer provider tokens
- global modules and exported module boundaries
- REST decorators
- request binding
- versioned routes, status codes, redirects, response headers, SSE, streaming files
- rendered templates and static asset module
- signed sessions and security headers
- middleware
- route-scoped middleware with exclusions
- file upload binding
- file validation
- custom param decorators
- mapped DTO helpers
- response serialization
- guards, pipes, interceptors, filters
- `@Catch` typed exception filters
- Reflector and DiscoveryService
- Swagger helpers and security schemes
- JWT auth and roles
- Passport-style strategy guards
- cache and throttling
- WebSocket gateways, Socket.IO-style room emitters, guards, pipes, filters, `MessageBody`, and `ConnectedSocket`
- cron, interval, timeout jobs, and scheduler registry
- in-memory queue processors
- queue retries and delayed jobs
- BullModule and InjectQueue aliases
- mailer package with templates
- CQRS package
- event emitter wildcard/once/off helpers
- microservice message/event patterns and named transports
- lightweight GraphQL module with queries, mutations, and subscriptions
- SQLAlchemy package start
- TypeOrmModule and InjectRepository aliases over SQLAlchemy
- migration template helper
- Mongo-style package start
- MongooseModule and InjectModel aliases
- i18n package
- cache store adapters
- health checks
- health indicators with disk and memory helpers
- metrics module
- worker task handlers
- testing utilities
- CLI generators
- workspace and library CLI commands

Still to deepen:

- live certification against real Redis, MongoDB, Postgres, RabbitMQ, NATS, Kafka, gRPC, and SMTP services
- a full migration runner
- production GraphQL validation depth comparable to dedicated GraphQL engines
- true Socket.IO protocol parity
- exact package-by-package NestJS polish for the long tail of decorator variants

The plan is to keep closing that gap package by package, without losing the Python feel.

## Repository Status

This is an early beta framework build, but it is runnable and tested.

```bash
uv run pytest
# 407 passed, 22 skipped
```

Current package candidate: `0.3.0b3`.

## License

MIT
