fanest 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. fanest-0.1.0/.gitignore +11 -0
  2. fanest-0.1.0/LICENSE +21 -0
  3. fanest-0.1.0/PKG-INFO +608 -0
  4. fanest-0.1.0/README.md +564 -0
  5. fanest-0.1.0/benchmarks/benchmark_test.py +61 -0
  6. fanest-0.1.0/examples/all_uses/__init__.py +1 -0
  7. fanest-0.1.0/examples/all_uses/main.py +249 -0
  8. fanest-0.1.0/examples/basic/__init__.py +1 -0
  9. fanest-0.1.0/examples/basic/main.py +25 -0
  10. fanest-0.1.0/pyproject.toml +87 -0
  11. fanest-0.1.0/src/fanest/__init__.py +205 -0
  12. fanest-0.1.0/src/fanest/auth/__init__.py +28 -0
  13. fanest-0.1.0/src/fanest/auth/jwt.py +194 -0
  14. fanest-0.1.0/src/fanest/auth/passport.py +55 -0
  15. fanest-0.1.0/src/fanest/cache/__init__.py +25 -0
  16. fanest-0.1.0/src/fanest/cache/module.py +140 -0
  17. fanest-0.1.0/src/fanest/cli/__init__.py +1 -0
  18. fanest-0.1.0/src/fanest/cli/main.py +666 -0
  19. fanest-0.1.0/src/fanest/common/__init__.py +146 -0
  20. fanest-0.1.0/src/fanest/common/decorators.py +284 -0
  21. fanest-0.1.0/src/fanest/common/exceptions.py +76 -0
  22. fanest-0.1.0/src/fanest/common/middleware.py +120 -0
  23. fanest-0.1.0/src/fanest/common/pipes.py +158 -0
  24. fanest-0.1.0/src/fanest/common/responses.py +57 -0
  25. fanest-0.1.0/src/fanest/common/serialization.py +67 -0
  26. fanest-0.1.0/src/fanest/config/__init__.py +3 -0
  27. fanest-0.1.0/src/fanest/config/module.py +115 -0
  28. fanest-0.1.0/src/fanest/core/__init__.py +37 -0
  29. fanest-0.1.0/src/fanest/core/application.py +99 -0
  30. fanest-0.1.0/src/fanest/core/container.py +529 -0
  31. fanest-0.1.0/src/fanest/core/discovery.py +32 -0
  32. fanest-0.1.0/src/fanest/core/enhancers.py +10 -0
  33. fanest-0.1.0/src/fanest/core/factory.py +262 -0
  34. fanest-0.1.0/src/fanest/core/metadata.py +114 -0
  35. fanest-0.1.0/src/fanest/core/module.py +68 -0
  36. fanest-0.1.0/src/fanest/core/module_ref.py +87 -0
  37. fanest-0.1.0/src/fanest/core/providers.py +43 -0
  38. fanest-0.1.0/src/fanest/core/reflector.py +34 -0
  39. fanest-0.1.0/src/fanest/core/scanner.py +236 -0
  40. fanest-0.1.0/src/fanest/cqrs/__init__.py +19 -0
  41. fanest-0.1.0/src/fanest/cqrs/module.py +91 -0
  42. fanest-0.1.0/src/fanest/events/__init__.py +3 -0
  43. fanest-0.1.0/src/fanest/events/module.py +54 -0
  44. fanest-0.1.0/src/fanest/graphql/__init__.py +3 -0
  45. fanest-0.1.0/src/fanest/graphql/module.py +110 -0
  46. fanest-0.1.0/src/fanest/health/__init__.py +17 -0
  47. fanest-0.1.0/src/fanest/health/module.py +105 -0
  48. fanest-0.1.0/src/fanest/http/__init__.py +3 -0
  49. fanest-0.1.0/src/fanest/http/module.py +65 -0
  50. fanest-0.1.0/src/fanest/i18n/__init__.py +3 -0
  51. fanest-0.1.0/src/fanest/i18n/module.py +67 -0
  52. fanest-0.1.0/src/fanest/logger/__init__.py +3 -0
  53. fanest-0.1.0/src/fanest/logger/module.py +38 -0
  54. fanest-0.1.0/src/fanest/mailer/__init__.py +3 -0
  55. fanest-0.1.0/src/fanest/mailer/module.py +90 -0
  56. fanest-0.1.0/src/fanest/mapped_types.py +56 -0
  57. fanest-0.1.0/src/fanest/metrics/__init__.py +3 -0
  58. fanest-0.1.0/src/fanest/metrics/module.py +63 -0
  59. fanest-0.1.0/src/fanest/microservices/__init__.py +39 -0
  60. fanest-0.1.0/src/fanest/microservices/module.py +203 -0
  61. fanest-0.1.0/src/fanest/mongodb/__init__.py +17 -0
  62. fanest-0.1.0/src/fanest/mongodb/module.py +104 -0
  63. fanest-0.1.0/src/fanest/platform_fastapi/__init__.py +3 -0
  64. fanest-0.1.0/src/fanest/platform_fastapi/adapter.py +741 -0
  65. fanest-0.1.0/src/fanest/platform_fastapi/modules.py +11 -0
  66. fanest-0.1.0/src/fanest/py.typed +1 -0
  67. fanest-0.1.0/src/fanest/queues/__init__.py +23 -0
  68. fanest-0.1.0/src/fanest/queues/module.py +181 -0
  69. fanest-0.1.0/src/fanest/schedule/__init__.py +14 -0
  70. fanest-0.1.0/src/fanest/schedule/decorators.py +67 -0
  71. fanest-0.1.0/src/fanest/schedule/registry.py +98 -0
  72. fanest-0.1.0/src/fanest/schedule/runner.py +88 -0
  73. fanest-0.1.0/src/fanest/security/__init__.py +3 -0
  74. fanest-0.1.0/src/fanest/security/module.py +55 -0
  75. fanest-0.1.0/src/fanest/serve_static/__init__.py +3 -0
  76. fanest-0.1.0/src/fanest/serve_static/module.py +20 -0
  77. fanest-0.1.0/src/fanest/session/__init__.py +3 -0
  78. fanest-0.1.0/src/fanest/session/module.py +109 -0
  79. fanest-0.1.0/src/fanest/sqlalchemy/__init__.py +23 -0
  80. fanest-0.1.0/src/fanest/sqlalchemy/module.py +285 -0
  81. fanest-0.1.0/src/fanest/swagger/__init__.py +64 -0
  82. fanest-0.1.0/src/fanest/swagger/decorators.py +330 -0
  83. fanest-0.1.0/src/fanest/swagger/module.py +188 -0
  84. fanest-0.1.0/src/fanest/testing/__init__.py +3 -0
  85. fanest-0.1.0/src/fanest/testing/module.py +97 -0
  86. fanest-0.1.0/src/fanest/throttler/__init__.py +3 -0
  87. fanest-0.1.0/src/fanest/throttler/module.py +100 -0
  88. fanest-0.1.0/src/fanest/websockets/__init__.py +3 -0
  89. fanest-0.1.0/src/fanest/websockets/manager.py +93 -0
  90. fanest-0.1.0/src/fanest/workers/__init__.py +3 -0
  91. fanest-0.1.0/src/fanest/workers/module.py +38 -0
  92. fanest-0.1.0/tests/test_advanced_di.py +85 -0
  93. fanest-0.1.0/tests/test_app_enhancers.py +83 -0
  94. fanest-0.1.0/tests/test_application.py +36 -0
  95. fanest-0.1.0/tests/test_auth_health.py +62 -0
  96. fanest-0.1.0/tests/test_auth_security_parity.py +76 -0
  97. fanest-0.1.0/tests/test_basic_app.py +34 -0
  98. fanest-0.1.0/tests/test_builtin_modules_batch.py +97 -0
  99. fanest-0.1.0/tests/test_cli.py +204 -0
  100. fanest-0.1.0/tests/test_common_completions.py +37 -0
  101. fanest-0.1.0/tests/test_config_testing_swagger.py +81 -0
  102. fanest-0.1.0/tests/test_cqrs_module.py +92 -0
  103. fanest-0.1.0/tests/test_deep_http.py +63 -0
  104. fanest-0.1.0/tests/test_discovery_service.py +34 -0
  105. fanest-0.1.0/tests/test_file_pipes.py +52 -0
  106. fanest-0.1.0/tests/test_framework_options.py +66 -0
  107. fanest-0.1.0/tests/test_gap_fixes.py +133 -0
  108. fanest-0.1.0/tests/test_global_modules_signature.py +105 -0
  109. fanest-0.1.0/tests/test_graphql_module.py +44 -0
  110. fanest-0.1.0/tests/test_http_parity_batch.py +92 -0
  111. fanest-0.1.0/tests/test_http_response_helpers.py +79 -0
  112. fanest-0.1.0/tests/test_i18n_bull.py +79 -0
  113. fanest-0.1.0/tests/test_lifecycle_hooks.py +72 -0
  114. fanest-0.1.0/tests/test_metrics_module.py +25 -0
  115. fanest-0.1.0/tests/test_middleware_mapped_microservices.py +196 -0
  116. fanest-0.1.0/tests/test_module_boundaries.py +220 -0
  117. fanest-0.1.0/tests/test_module_config_isolation.py +38 -0
  118. fanest-0.1.0/tests/test_module_global_async.py +242 -0
  119. fanest-0.1.0/tests/test_module_ref.py +183 -0
  120. fanest-0.1.0/tests/test_mongodb_module.py +63 -0
  121. fanest-0.1.0/tests/test_passport_auth.py +55 -0
  122. fanest-0.1.0/tests/test_platform_health_filters.py +93 -0
  123. fanest-0.1.0/tests/test_production_readiness.py +54 -0
  124. fanest-0.1.0/tests/test_provider_scopes.py +123 -0
  125. fanest-0.1.0/tests/test_queue_mailer.py +120 -0
  126. fanest-0.1.0/tests/test_reflector.py +42 -0
  127. fanest-0.1.0/tests/test_request_pipeline.py +132 -0
  128. fanest-0.1.0/tests/test_schedule_cache_throttler.py +225 -0
  129. fanest-0.1.0/tests/test_sqlalchemy_orm.py +105 -0
  130. fanest-0.1.0/tests/test_static_render.py +39 -0
  131. fanest-0.1.0/tests/test_swagger_module.py +116 -0
  132. fanest-0.1.0/tests/test_testing_overrides.py +173 -0
  133. fanest-0.1.0/tests/test_websockets.py +226 -0
  134. fanest-0.1.0/tests/test_workers_module.py +35 -0
  135. fanest-0.1.0/uv.lock +1653 -0
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .mypy_cache/
8
+ .DS_Store
9
+ fanest-example.db
10
+ dist/
11
+ build/
fanest-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ahfoysal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
fanest-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,608 @@
1
+ Metadata-Version: 2.4
2
+ Name: fanest
3
+ Version: 0.1.0
4
+ Summary: NestJS-style backend architecture for Python, powered by FastAPI.
5
+ Project-URL: Homepage, https://github.com/ahfoysal/fanest
6
+ Project-URL: Repository, https://github.com/ahfoysal/fanest
7
+ Project-URL: Issues, https://github.com/ahfoysal/fanest/issues
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: backend,dependency-injection,fastapi,framework,nestjs,python
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Framework :: FastAPI
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: aiosqlite>=0.20.0
23
+ Requires-Dist: croniter>=3.0.0
24
+ Requires-Dist: email-validator>=2.2.0
25
+ Requires-Dist: fastapi>=0.115.0
26
+ Requires-Dist: greenlet>=3.0.0
27
+ Requires-Dist: httpx>=0.27.0
28
+ Requires-Dist: pydantic>=2.0.0
29
+ Requires-Dist: pyjwt>=2.8.0
30
+ Requires-Dist: python-multipart>=0.0.9
31
+ Requires-Dist: sqlalchemy>=2.0.0
32
+ Requires-Dist: typer>=0.12.0
33
+ Requires-Dist: uvicorn>=0.30.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: build>=1.2.0; extra == 'dev'
36
+ Requires-Dist: pyright>=1.1.411; extra == 'dev'
37
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
38
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
39
+ Requires-Dist: tomli>=2.0.0; (python_version < '3.11') and extra == 'dev'
40
+ Requires-Dist: twine>=6.0.0; extra == 'dev'
41
+ Provides-Extra: standard
42
+ Requires-Dist: uvicorn[standard]>=0.30.0; extra == 'standard'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # FaNest
46
+
47
+ A progressive Python framework for building structured, scalable, and maintainable backend applications.
48
+
49
+ 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.
50
+
51
+ It is built for developers who like the NestJS workflow but want to work in Python.
52
+
53
+ ## Description
54
+
55
+ Python has excellent web libraries, but larger applications still need a repeatable structure. FaNest provides that structure without hiding the Python ecosystem.
56
+
57
+ The framework combines:
58
+
59
+ - class-based modules, controllers, services, and gateways
60
+ - constructor-based dependency injection
61
+ - decorator-driven routing and WebSocket messages
62
+ - request pipeline layers: guards, pipes, interceptors, and filters
63
+ - FastAPI, Pydantic, SQLAlchemy, and pytest-friendly defaults
64
+ - a CLI shaped around everyday backend work
65
+
66
+ FaNest is inspired by NestJS, but it is not a wrapper around NestJS and is not affiliated with the NestJS project.
67
+
68
+ ## Philosophy
69
+
70
+ 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.
71
+
72
+ FaNest should feel predictable in a growing codebase:
73
+
74
+ - modules describe boundaries
75
+ - providers hold business logic
76
+ - controllers stay thin
77
+ - decorators make framework behavior visible
78
+ - tests can override dependencies without patching imports
79
+ - packages can plug into the same module system
80
+
81
+ Small APIs should stay small. Bigger APIs should not become a pile of unrelated route functions.
82
+
83
+ ## Getting Started
84
+
85
+ ```bash
86
+ uv sync --extra dev
87
+ uv run fanest dev examples/basic/main.py
88
+ ```
89
+
90
+ Open:
91
+
92
+ ```txt
93
+ http://127.0.0.1:8000/docs
94
+ ```
95
+
96
+ ## A Small Application
97
+
98
+ ```python
99
+ from pydantic import BaseModel
100
+
101
+ from fanest import Body, Controller, FaNestFactory, Get, Injectable, Module, Post
102
+
103
+
104
+ class CreateUserDto(BaseModel):
105
+ name: str
106
+
107
+
108
+ @Injectable()
109
+ class UsersService:
110
+ def __init__(self):
111
+ self.users = []
112
+
113
+ def find_all(self):
114
+ return self.users
115
+
116
+ def create(self, dto: CreateUserDto):
117
+ user = {"id": len(self.users) + 1, "name": dto.name}
118
+ self.users.append(user)
119
+ return user
120
+
121
+
122
+ @Controller("users")
123
+ class UsersController:
124
+ def __init__(self, users_service: UsersService):
125
+ self.users_service = users_service
126
+
127
+ @Get("/")
128
+ async def find_all(self):
129
+ return self.users_service.find_all()
130
+
131
+ @Post("/")
132
+ async def create(self, dto: CreateUserDto = Body()):
133
+ return self.users_service.create(dto)
134
+
135
+
136
+ @Module(controllers=[UsersController], providers=[UsersService])
137
+ class AppModule:
138
+ pass
139
+
140
+
141
+ app = FaNestFactory.create(AppModule)
142
+ ```
143
+
144
+ ## All Uses Example
145
+
146
+ The fuller example lives in [examples/all_uses/main.py](/Users/foysal/fanest/examples/all_uses/main.py).
147
+
148
+ It shows:
149
+
150
+ - REST controllers
151
+ - Pydantic DTOs
152
+ - mapped DTO helpers
153
+ - constructor injection
154
+ - custom provider tokens
155
+ - middleware
156
+ - file uploads
157
+ - file validation pipes
158
+ - response headers, SSE, and streaming files
159
+ - rendered templates and static assets
160
+ - session cookies and security headers
161
+ - custom parameter decorators
162
+ - config module
163
+ - config validation helpers
164
+ - async module configuration
165
+ - i18n translations and locale extraction
166
+ - JWT auth
167
+ - Passport-style auth strategies
168
+ - role guards
169
+ - cache interceptor
170
+ - cache stores
171
+ - throttling guard
172
+ - Swagger document setup, security schemes, and TypeScript client generation
173
+ - typed exception filters
174
+ - Reflector and discovery services
175
+ - health indicators
176
+ - disk and memory health checks
177
+ - metrics counters
178
+ - worker task handlers
179
+ - GraphQL resolvers and subscriptions
180
+ - health endpoint
181
+ - SQLAlchemy module wiring
182
+ - TypeORM-style repository injection over SQLAlchemy
183
+ - Mongo-style document collections
184
+ - Mongoose-style module aliases
185
+ - interval jobs
186
+ - cron jobs
187
+ - timeout jobs and scheduler registry
188
+ - queue processors
189
+ - Bull-style queue aliases
190
+ - mailer service
191
+ - CQRS command/query/event buses
192
+ - event emitter wildcard, once, and off helpers
193
+ - named microservice transports
194
+ - WebSocket gateway with rooms, broadcasting, guards, pipes, filters, message-body decorators, connected-socket decorators, and Socket.IO-style emitters
195
+ - global prefix, CORS, and global pipes
196
+ - `APP_GUARD`, `APP_PIPE`, `APP_INTERCEPTOR`, and `APP_FILTER` global providers
197
+
198
+ Run it:
199
+
200
+ ```bash
201
+ uv run uvicorn examples.all_uses.main:app --reload
202
+ ```
203
+
204
+ Useful paths:
205
+
206
+ ```txt
207
+ GET /api/users
208
+ POST /api/users
209
+ POST /api/users/login
210
+ GET /api/admin/me
211
+ GET /api/health
212
+ GET /api/docs
213
+ WS /api/chat
214
+ ```
215
+
216
+ ## CLI
217
+
218
+ ```bash
219
+ fanest new blog-api
220
+ fanest workspace acme-platform
221
+ fanest start main:app --reload
222
+ fanest dev main.py
223
+ fanest run main.py
224
+ fanest run src/main.py --app application --workers 2
225
+
226
+ fanest generate resource users
227
+ fanest generate module users
228
+ fanest generate controller users
229
+ fanest generate service users
230
+ fanest generate guard auth
231
+ fanest generate pipe validation
232
+ fanest generate interceptor logging
233
+ fanest generate filter http_error
234
+ fanest generate gateway chat
235
+ fanest generate dto users
236
+ fanest generate middleware request_id
237
+ fanest generate decorator current_user
238
+ fanest generate library common
239
+ fanest generate resource users --dry-run
240
+ fanest generate module users --module app_module.py
241
+ ```
242
+
243
+ ## Core Features
244
+
245
+ FaNest currently includes:
246
+
247
+ - `@Module`
248
+ - `@Controller`
249
+ - `@Injectable`
250
+ - `@Get`, `@Post`, `@Put`, `@Patch`, `@Delete`, `@Options`, `@Head`, `@All`
251
+ - `Body`, `Param`, `Query`, `Header`, `Headers`, `Cookie`, `Req`, `Res`, `Ip`, `HostParam`, `Session`
252
+ - `UploadedFile`, `UploadedFiles`, `BackgroundTasks`, custom param decorators
253
+ - `HttpCode`, `Redirect`, `SetHeader`, `SetMetadata`, `Version`, `ResponseModel`
254
+ - `Sse` and `StreamableFile`
255
+ - `UseGuards`
256
+ - `UsePipes`
257
+ - `UseInterceptors`
258
+ - `UseFilters`
259
+ - `WebSocketGateway`
260
+ - `SubscribeMessage`
261
+ - `MessageBody`
262
+ - `ConnectedSocket`
263
+ - `Interval`
264
+ - `Cron`
265
+ - `Timeout`
266
+ - `Global`
267
+ - `MessagePattern`
268
+ - `EventPattern`
269
+ - lifecycle hooks: `on_module_init`, `on_application_shutdown`
270
+
271
+ ## Dependency Injection
272
+
273
+ FaNest supports class providers and Nest-style provider definitions:
274
+
275
+ ```python
276
+ from fanest import Inject, Injectable, Module, token, use_factory, use_value
277
+
278
+ CONFIG = token("CONFIG")
279
+ MESSAGE = token("MESSAGE")
280
+
281
+
282
+ @Injectable()
283
+ class MessageService:
284
+ def __init__(self, message: str = Inject(MESSAGE)):
285
+ self.message = message
286
+
287
+
288
+ @Module(
289
+ providers=[
290
+ MessageService,
291
+ use_value(CONFIG, {"message": "hello"}),
292
+ use_factory(MESSAGE, lambda config: config["message"], inject=[CONFIG]),
293
+ ],
294
+ )
295
+ class MessageModule:
296
+ pass
297
+ ```
298
+
299
+ Supported provider types:
300
+
301
+ - class providers
302
+ - value providers
303
+ - factory providers
304
+ - async factory providers
305
+ - existing provider aliases
306
+ - injection tokens
307
+ - optional injection
308
+ - singleton, request, and transient scopes
309
+ - `forward_ref`
310
+ - global modules
311
+ - provider overrides in tests
312
+
313
+ ## Packages
314
+
315
+ The repository already contains first-party package starts:
316
+
317
+ ```txt
318
+ fanest.core modules, DI, scanner, app factory
319
+ fanest.common decorators, exceptions, pipes
320
+ fanest.platform_fastapi FastAPI adapter
321
+ fanest.session signed cookie sessions
322
+ fanest.security helmet-style security headers
323
+ fanest.i18n translations and I18nLang helper
324
+ fanest.config ConfigModule and ConfigService
325
+ fanest.swagger decorators, DocumentBuilder, SwaggerModule
326
+ fanest.auth JWT service, passport strategies, auth guard, roles guard
327
+ fanest.sqlalchemy async SQLAlchemy module, repositories, TypeOrmModule alias
328
+ fanest.mongodb Mongo/Mongoose-style document service and collections
329
+ fanest.cache cache service, interceptor, and store adapters
330
+ fanest.throttler throttling module and guard
331
+ fanest.schedule interval, cron, timeout jobs, scheduler registry
332
+ fanest.websockets connection manager, rooms, broadcasting, Socket.IO-style server
333
+ fanest.serve_static static asset module
334
+ fanest.queues QueueModule/BullModule, processors, jobs
335
+ fanest.mailer mail service with outbox and SMTP handoff
336
+ fanest.cqrs command, query, and event buses
337
+ fanest.events event emitter and OnEvent decorators
338
+ fanest.graphql resolvers, queries, mutations, subscriptions, GraphQL endpoint
339
+ fanest.microservices message/event patterns and named transports
340
+ fanest.mapped_types PartialType, PickType, OmitType, IntersectionType
341
+ fanest.health health endpoint module with reusable indicators
342
+ fanest.metrics counters and metrics endpoint
343
+ fanest.workers task handler registry
344
+ fanest.discovery/core Reflector and DiscoveryService
345
+ fanest.testing TestingModule and provider overrides
346
+ ```
347
+
348
+ ## Built-In Pipes And Exceptions
349
+
350
+ Pipes:
351
+
352
+ - `ValidationPipe`
353
+ - `ParseIntPipe`
354
+ - `ParseBoolPipe`
355
+ - `ParseFloatPipe`
356
+ - `ParseUUIDPipe`
357
+ - `ParseEnumPipe`
358
+ - `ParseArrayPipe`
359
+ - `DefaultValuePipe`
360
+ - `ParseFilePipe`
361
+ - `MaxFileSizeValidator`
362
+ - `FileTypeValidator`
363
+
364
+ Exceptions:
365
+
366
+ - `BadRequestException`
367
+ - `UnauthorizedException`
368
+ - `ForbiddenException`
369
+ - `NotFoundException`
370
+ - `ConflictException`
371
+ - `InternalServerErrorException`
372
+ - `UnprocessableEntityException`
373
+ - `TooManyRequestsException`
374
+ - `ServiceUnavailableException`
375
+
376
+ ## Swagger
377
+
378
+ ```python
379
+ from fanest.swagger import DocumentBuilder, SwaggerModule
380
+
381
+ config = (
382
+ DocumentBuilder()
383
+ .set_title("Blog API")
384
+ .set_description("A FaNest application")
385
+ .set_version("1.0.0")
386
+ .add_bearer_auth()
387
+ .build()
388
+ )
389
+
390
+ document = SwaggerModule.create_document(app, config)
391
+ SwaggerModule.setup("/docs", app, document)
392
+ ```
393
+
394
+ Swagger decorators include `ApiTags`, `ApiOperation`, `ApiParam`, `ApiQuery`, `ApiHeader`,
395
+ `ApiBody`, `ApiResponse`, `ApiConsumes`, `ApiProduces`, `ApiBearerAuth`, `ApiBasicAuth`,
396
+ `ApiCookieAuth`, `ApiSecurity`, `ApiExtraModels`, `ApiExtension`, response shortcuts such as
397
+ `ApiOkResponse`, `ApiCreatedResponse`, `ApiNotFoundResponse`, `ApiExcludeEndpoint`,
398
+ `ApiProperty`, `ApiPropertyOptional`, and `ApiHideProperty`.
399
+ `SwaggerModule.generate_typescript_client(document)` can emit a small fetch client from the
400
+ generated OpenAPI document.
401
+
402
+ ## WebSockets
403
+
404
+ ```python
405
+ from fanest import ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway
406
+
407
+
408
+ @WebSocketGateway("/chat")
409
+ class ChatGateway:
410
+ @SubscribeMessage("rename")
411
+ async def rename(self, name: str = MessageBody("name"), socket=ConnectedSocket()):
412
+ return {"name": name}
413
+ ```
414
+
415
+ Gateways can use guards, pipes, filters, rooms, broadcast helpers, and `SocketIoServer` for
416
+ the familiar `server.to("room").emit(...)` shape.
417
+
418
+ ## Health Checks
419
+
420
+ ```python
421
+ from fanest.health import DiskHealthIndicator, HealthIndicator, HealthModule, MemoryHealthIndicator
422
+
423
+
424
+ HealthModule.register(
425
+ [
426
+ HealthIndicator("database", lambda: {"status": "ok"}),
427
+ DiskHealthIndicator(path="/"),
428
+ MemoryHealthIndicator(rss_threshold_mb=512),
429
+ ]
430
+ )
431
+ ```
432
+
433
+ ## Mapped Types
434
+
435
+ ```python
436
+ from fanest import PartialType, PickType
437
+
438
+ UpdateUserDto = PartialType(CreateUserDto)
439
+ PublicUserDto = PickType(UserDto, ["id", "name"])
440
+ ```
441
+
442
+ ## ORM
443
+
444
+ FaNest ships with an async SQLAlchemy package and Nest-style repository injection:
445
+
446
+ ```python
447
+ from fanest import Injectable, Module
448
+ from fanest.sqlalchemy import InjectRepository, SqlAlchemyRepository, TypeOrmModule
449
+
450
+
451
+ @Injectable()
452
+ class UsersService:
453
+ def __init__(self, users: SqlAlchemyRepository = InjectRepository(User)):
454
+ self.users = users
455
+
456
+
457
+ @Module(
458
+ imports=[
459
+ TypeOrmModule.for_root(database_url="sqlite+aiosqlite:///app.db"),
460
+ TypeOrmModule.for_feature([User]),
461
+ ],
462
+ providers=[UsersService],
463
+ )
464
+ class UsersModule:
465
+ pass
466
+ ```
467
+
468
+ Repositories include `find_all`, `find_by`, `find_one`, `find_one_by`, `count`, `save`,
469
+ `update`, `delete`, and `delete_by`. `SqlAlchemyModule` and `TypeOrmModule` point to the same
470
+ Python-native SQLAlchemy integration, so Nest users can keep the familiar module shape while
471
+ still using SQLAlchemy models.
472
+
473
+ ## Middleware
474
+
475
+ ```python
476
+ class RequestIdMiddleware:
477
+ async def use(self, request, call_next):
478
+ response = await call_next(request)
479
+ response.headers["x-request-id"] = "local"
480
+ return response
481
+
482
+
483
+ @Module(controllers=[UsersController], middlewares=[RequestIdMiddleware])
484
+ class AppModule:
485
+ pass
486
+ ```
487
+
488
+ Modules can also expose a Nest-style `configure(consumer)` method for route-scoped
489
+ middleware with exclusions:
490
+
491
+ ```python
492
+ class AppModule:
493
+ def configure(self, consumer):
494
+ consumer.apply(RequestIdMiddleware).exclude("/health").for_routes("/users*")
495
+ ```
496
+
497
+ ## Microservices
498
+
499
+ ```python
500
+ from fanest.microservices import MessagePattern, MicroserviceServer
501
+
502
+
503
+ class MathService:
504
+ @MessagePattern("math.double")
505
+ async def double(self, data, context):
506
+ return data * 2
507
+
508
+
509
+ server = MicroserviceServer(AppModule).compile()
510
+ client = server.client()
511
+ result = await client.send("math.double", 21)
512
+ ```
513
+
514
+ ## Testing
515
+
516
+ ```python
517
+ from fanest.testing import TestingModule
518
+
519
+ app = (
520
+ TestingModule.create(AppModule)
521
+ .override_provider(UsersService, MockUsersService())
522
+ .compile()
523
+ )
524
+ ```
525
+
526
+ Run the test suite:
527
+
528
+ ```bash
529
+ uv run pytest
530
+ uv run ruff check .
531
+ ```
532
+
533
+ ## NestJS Parity
534
+
535
+ 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.
536
+
537
+ Current:
538
+
539
+ - modules, controllers, providers
540
+ - DI with custom, async, scoped, optional, and aliased providers
541
+ - `APP_GUARD`, `APP_PIPE`, `APP_INTERCEPTOR`, and `APP_FILTER` global enhancer provider tokens
542
+ - global modules and exported module boundaries
543
+ - REST decorators
544
+ - request binding
545
+ - versioned routes, status codes, redirects, response headers, SSE, streaming files
546
+ - rendered templates and static asset module
547
+ - signed sessions and security headers
548
+ - middleware
549
+ - route-scoped middleware with exclusions
550
+ - file upload binding
551
+ - file validation
552
+ - custom param decorators
553
+ - mapped DTO helpers
554
+ - response serialization
555
+ - guards, pipes, interceptors, filters
556
+ - `@Catch` typed exception filters
557
+ - Reflector and DiscoveryService
558
+ - Swagger helpers and security schemes
559
+ - JWT auth and roles
560
+ - Passport-style strategy guards
561
+ - cache and throttling
562
+ - WebSocket gateways, Socket.IO-style room emitters, guards, pipes, filters, `MessageBody`, and `ConnectedSocket`
563
+ - cron, interval, timeout jobs, and scheduler registry
564
+ - in-memory queue processors
565
+ - queue retries and delayed jobs
566
+ - BullModule and InjectQueue aliases
567
+ - mailer package with templates
568
+ - CQRS package
569
+ - event emitter wildcard/once/off helpers
570
+ - microservice message/event patterns and named transports
571
+ - lightweight GraphQL module with queries, mutations, and subscriptions
572
+ - SQLAlchemy package start
573
+ - TypeOrmModule and InjectRepository aliases over SQLAlchemy
574
+ - migration template helper
575
+ - Mongo-style package start
576
+ - MongooseModule and InjectModel aliases
577
+ - i18n package
578
+ - cache store adapters
579
+ - health checks
580
+ - health indicators with disk and memory helpers
581
+ - metrics module
582
+ - worker task handlers
583
+ - testing utilities
584
+ - CLI generators
585
+ - workspace and library CLI commands
586
+
587
+ Still to deepen:
588
+
589
+ - Redis-backed queue transport
590
+ - advanced SMTP provider adapters
591
+ - full migration runner
592
+ - deeper GraphQL schema generation
593
+ - networked microservice drivers beyond the in-process transport contract
594
+
595
+ The plan is to keep closing that gap package by package, without losing the Python feel.
596
+
597
+ ## Repository Status
598
+
599
+ This is an early framework build, but it is runnable and tested.
600
+
601
+ ```bash
602
+ uv run pytest
603
+ # 90 passed
604
+ ```
605
+
606
+ ## License
607
+
608
+ MIT