fastapi-modular 0.2.0__tar.gz → 0.2.1__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 (163) hide show
  1. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/CHANGELOG.md +18 -0
  2. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/LICENSE +1 -1
  3. fastapi_modular-0.2.1/PKG-INFO +412 -0
  4. fastapi_modular-0.2.1/README.md +342 -0
  5. fastapi_modular-0.2.0/README.md → fastapi_modular-0.2.1/README.vi.md +31 -6
  6. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/README.md +1 -1
  7. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/operations.md +2 -2
  8. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/rabbitmq.md +1 -1
  9. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/websocket.md +368 -223
  10. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/__init__.py +1 -1
  11. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/pyproject.toml +19 -5
  12. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_settings_mo_rong.py +2 -2
  13. fastapi_modular-0.2.0/PKG-INFO +0 -377
  14. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/.gitignore +0 -0
  15. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/Makefile +0 -0
  16. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/alembic.ini +0 -0
  17. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/architecture.md +0 -0
  18. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/config.md +0 -0
  19. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/database.md +0 -0
  20. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/kafka.md +0 -0
  21. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/migrations.md +0 -0
  22. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/mqtt.md +0 -0
  23. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/redis.md +0 -0
  24. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/__init__.py +0 -0
  25. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/clean.py +0 -0
  26. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/configure_env.py +0 -0
  27. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/cong_cu.py +0 -0
  28. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/info.py +0 -0
  29. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/install.py +0 -0
  30. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/main.py +0 -0
  31. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/new_module.py +0 -0
  32. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/new_project.py +0 -0
  33. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/serve.py +0 -0
  34. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/__init__.py +0 -0
  35. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/clock.py +0 -0
  36. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/compat.py +0 -0
  37. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/config.py +0 -0
  38. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/container.py +0 -0
  39. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/context.py +0 -0
  40. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/controller.py +0 -0
  41. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/error_handlers.py +0 -0
  42. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/exceptions.py +0 -0
  43. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/guards.py +0 -0
  44. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/lifespan.py +0 -0
  45. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/logging.py +0 -0
  46. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/metrics.py +0 -0
  47. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/schemas.py +0 -0
  48. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/__init__.py +0 -0
  49. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/adapter.py +0 -0
  50. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/gateway.py +0 -0
  51. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/namespace.py +0 -0
  52. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/protocol.py +0 -0
  53. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/server.py +0 -0
  54. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/socket.py +0 -0
  55. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/discovery.py +0 -0
  56. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/factory.py +0 -0
  57. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/__init__.py +0 -0
  58. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/__init__.py +0 -0
  59. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/base.py +0 -0
  60. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/circuit.py +0 -0
  61. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/factory.py +0 -0
  62. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/memory.py +0 -0
  63. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/mongo.py +0 -0
  64. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/repository.py +0 -0
  65. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/sql.py +0 -0
  66. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/__init__.py +0 -0
  67. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/broker.py +0 -0
  68. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/consumers.py +0 -0
  69. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/metrics.py +0 -0
  70. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/__init__.py +0 -0
  71. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/client.py +0 -0
  72. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/consumers.py +0 -0
  73. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/metrics.py +0 -0
  74. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/patterns.py +0 -0
  75. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/__init__.py +0 -0
  76. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/broker.py +0 -0
  77. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/consumers.py +0 -0
  78. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/metrics.py +0 -0
  79. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/patterns.py +0 -0
  80. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/__init__.py +0 -0
  81. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/client.py +0 -0
  82. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/metrics.py +0 -0
  83. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/pubsub.py +0 -0
  84. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/middleware/__init__.py +0 -0
  85. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/middleware/request_context.py +0 -0
  86. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/py.typed +0 -0
  87. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/env.py +0 -0
  88. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/script.py.mako +0 -0
  89. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/versions/.gitkeep +0 -0
  90. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/versions/20260821_1020_tao_bang_users_va_devices.py +0 -0
  91. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/pytest.ini +0 -0
  92. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/ruff.toml +0 -0
  93. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/__init__.py +0 -0
  94. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/__init__.py +0 -0
  95. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/__init__.py +0 -0
  96. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/chat_controller.py +0 -0
  97. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/chat_gateway.py +0 -0
  98. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/dto/__init__.py +0 -0
  99. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/dto/chat_dto.py +0 -0
  100. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/__init__.py +0 -0
  101. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/device_controller.py +0 -0
  102. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/device_service.py +0 -0
  103. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/dto/__init__.py +0 -0
  104. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/dto/device_dto.py +0 -0
  105. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/entities/__init__.py +0 -0
  106. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/entities/device_model.py +0 -0
  107. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/health/__init__.py +0 -0
  108. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/health/health_controller.py +0 -0
  109. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/__init__.py +0 -0
  110. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/kafka_consumer.py +0 -0
  111. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/kafka_controller.py +0 -0
  112. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/metrics/__init__.py +0 -0
  113. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/metrics/metrics_controller.py +0 -0
  114. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/__init__.py +0 -0
  115. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/mqtt_controller.py +0 -0
  116. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/mqtt_listener.py +0 -0
  117. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/__init__.py +0 -0
  118. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/rabbitmq_consumer.py +0 -0
  119. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/rabbitmq_controller.py +0 -0
  120. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/__init__.py +0 -0
  121. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/redis_controller.py +0 -0
  122. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/redis_listener.py +0 -0
  123. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/__init__.py +0 -0
  124. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/dto/__init__.py +0 -0
  125. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/dto/user_dto.py +0 -0
  126. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/entities/__init__.py +0 -0
  127. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/entities/user_model.py +0 -0
  128. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/user_controller.py +0 -0
  129. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/user_service.py +0 -0
  130. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/__init__.py +0 -0
  131. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/config.py +0 -0
  132. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/lifespan.py +0 -0
  133. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/main.py +0 -0
  134. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/conftest.py +0 -0
  135. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_circuit.py +0 -0
  136. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_cli.py +0 -0
  137. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_configure_env.py +0 -0
  138. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_container.py +0 -0
  139. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_cross_module.py +0 -0
  140. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_database.py +0 -0
  141. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_drivers.py +0 -0
  142. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_guards.py +0 -0
  143. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_ha_tang_that.py +0 -0
  144. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_health.py +0 -0
  145. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_kafka.py +0 -0
  146. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_kafka_offline.py +0 -0
  147. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_lifespan_rieng.py +0 -0
  148. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_metrics.py +0 -0
  149. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_module_generator.py +0 -0
  150. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_mqtt.py +0 -0
  151. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_mqtt_offline.py +0 -0
  152. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_rabbitmq.py +0 -0
  153. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_rabbitmq_offline.py +0 -0
  154. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_redis.py +0 -0
  155. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_redis_offline.py +0 -0
  156. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_resilience.py +0 -0
  157. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_schema_evolution.py +0 -0
  158. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_schemas.py +0 -0
  159. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_tuong_thich_phien_ban.py +0 -0
  160. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_uniqueness.py +0 -0
  161. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_users_api.py +0 -0
  162. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_websocket.py +0 -0
  163. {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_ws_adapter.py +0 -0
@@ -5,6 +5,24 @@ Theo [Keep a Changelog](https://keepachangelog.com/vi/1.1.0/); phiên bản theo
5
5
 
6
6
  ## [Chưa phát hành]
7
7
 
8
+ ## [0.2.1] — 2026-08-22
9
+
10
+ ### Thay đổi
11
+
12
+ - Tác giả và chủ bản quyền: Oryza <developer@oryza.vn> -> quanglinh
13
+ <hackcoquanglinh2000@gmail.com>, ở cả `pyproject.toml` lẫn `LICENSE`.
14
+ - README tách làm hai bản song ngữ: `README.md` (tiếng Anh, là bản hiện trên
15
+ PyPI) và `README.vi.md` (tiếng Việt). Hai bản giữ cùng thứ tự mục.
16
+ - Metadata PyPI viết lại cho tìm kiếm: summary sang tiếng Anh, keywords từ 9 lên
17
+ 39 từ, thêm 7 classifier.
18
+
19
+ ### Tài liệu
20
+
21
+ - Viết lại `docs/websocket.md` theo hướng làm-theo thay vì tra-cứu: đưa "bốn
22
+ việc client bắt buộc phải làm" lên đầu trang, thêm client tối thiểu 30 dòng
23
+ chạy được ngay, giải thích cơ chế nhịp tim bằng sơ đồ thời gian, và thêm mục
24
+ tra sự cố theo triệu chứng.
25
+
8
26
  ## [0.2.0] — 2026-08-22
9
27
 
10
28
  **Đổi tên toàn bộ.** Tên `pymodular` bị PyPI từ chối vì trùng với project
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Oryza
3
+ Copyright (c) 2026 quanglinh
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,412 @@
1
+ Metadata-Version: 2.5
2
+ Name: fastapi-modular
3
+ Version: 0.2.1
4
+ Summary: NestJS-style modular architecture for FastAPI: DI container, class-based controllers, auto-discovered modules, WebSocket gateway, RabbitMQ/Redis/MQTT/Kafka
5
+ Project-URL: Homepage, https://github.com/quanglinh2909/fastapi-modular
6
+ Project-URL: Documentation, https://github.com/quanglinh2909/fastapi-modular/tree/main/docs
7
+ Project-URL: Source, https://github.com/quanglinh2909/fastapi-modular
8
+ Project-URL: Issues, https://github.com/quanglinh2909/fastapi-modular/issues
9
+ Project-URL: Changelog, https://github.com/quanglinh2909/fastapi-modular/blob/main/CHANGELOG.md
10
+ Author-email: quanglinh <hackcoquanglinh2000@gmail.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: alembic,amqp,api,architecture,async,asyncio,boilerplate,cli,container,controller,decorator,dependency-injection,di,fastapi,framework,gateway,ioc,iot,kafka,microservices,modular,modular-monolith,module,mongodb,mqtt,nest,nestjs,postgresql,pubsub,rabbitmq,realtime,redis,repository,rest,scaffold,sqlalchemy,sqlite,websocket,websockets
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Framework :: AsyncIO
16
+ Classifier: Framework :: FastAPI
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Natural Language :: English
20
+ Classifier: Natural Language :: Vietnamese
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Topic :: Internet :: WWW/HTTP
27
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
28
+ Classifier: Topic :: System :: Distributed Computing
29
+ Classifier: Typing :: Typed
30
+ Requires-Python: >=3.10
31
+ Requires-Dist: fastapi<1.0.0,>=0.115.0
32
+ Requires-Dist: pydantic-settings<3.0.0,>=2.6.0
33
+ Requires-Dist: pydantic<3.0.0,>=2.9.0
34
+ Requires-Dist: structlog>=24.4.0
35
+ Requires-Dist: uvicorn[standard]<1.0.0,>=0.32.0
36
+ Provides-Extra: all
37
+ Requires-Dist: aio-pika<10.0.0,>=9.4.0; extra == 'all'
38
+ Requires-Dist: aiokafka<0.13.0,>=0.10.0; extra == 'all'
39
+ Requires-Dist: aiomqtt<3.0.0,>=2.0.0; extra == 'all'
40
+ Requires-Dist: aiosqlite>=0.20.0; extra == 'all'
41
+ Requires-Dist: alembic>=1.13.0; extra == 'all'
42
+ Requires-Dist: asyncpg>=0.29.0; extra == 'all'
43
+ Requires-Dist: motor<4.0.0,>=3.6.0; extra == 'all'
44
+ Requires-Dist: redis<7.0.0,>=5.0.0; extra == 'all'
45
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.30; extra == 'all'
46
+ Provides-Extra: dev
47
+ Requires-Dist: httpx>=0.27.0; extra == 'dev'
48
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
49
+ Requires-Dist: pytest>=8.3.0; extra == 'dev'
50
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
51
+ Provides-Extra: kafka
52
+ Requires-Dist: aiokafka<0.13.0,>=0.10.0; extra == 'kafka'
53
+ Provides-Extra: mongodb
54
+ Requires-Dist: motor<4.0.0,>=3.6.0; extra == 'mongodb'
55
+ Provides-Extra: mqtt
56
+ Requires-Dist: aiomqtt<3.0.0,>=2.0.0; extra == 'mqtt'
57
+ Provides-Extra: postgres
58
+ Requires-Dist: alembic>=1.13.0; extra == 'postgres'
59
+ Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
60
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.30; extra == 'postgres'
61
+ Provides-Extra: rabbitmq
62
+ Requires-Dist: aio-pika<10.0.0,>=9.4.0; extra == 'rabbitmq'
63
+ Provides-Extra: redis
64
+ Requires-Dist: redis<7.0.0,>=5.0.0; extra == 'redis'
65
+ Provides-Extra: sqlite
66
+ Requires-Dist: aiosqlite>=0.20.0; extra == 'sqlite'
67
+ Requires-Dist: alembic>=1.13.0; extra == 'sqlite'
68
+ Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.30; extra == 'sqlite'
69
+ Description-Content-Type: text/markdown
70
+
71
+ > **English** · [Tiếng Việt](https://github.com/quanglinh2909/fastapi-modular/blob/main/README.vi.md)
72
+
73
+ # fastapi-modular
74
+
75
+ **NestJS-style modular architecture for FastAPI.** A dependency-injection
76
+ container, class-based controllers, auto-discovered modules, a shared repository
77
+ over four databases, a WebSocket gateway with rooms, and optional RabbitMQ /
78
+ Redis / MQTT / Kafka layers that stay dormant until you enable them.
79
+
80
+ If you have written NestJS and wished FastAPI came with the same structure —
81
+ modules that register themselves, `@Injectable` services, `@Controller` classes,
82
+ `@WebSocketGateway`, `@EventPattern` — this is that, in Python.
83
+
84
+ ```bash
85
+ pip install fastapi-modular
86
+ fam init && fam dev
87
+ ```
88
+
89
+ The full documentation lives in `docs/` and is written in **Vietnamese**; the
90
+ public API, and this README, are in English. Start with
91
+ [docs/architecture.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/architecture.md).
92
+
93
+ ## Coming from NestJS?
94
+
95
+ | NestJS | fastapi-modular |
96
+ |---|---|
97
+ | `@Module()` + module scanning | a directory under `src/api/`, auto-scanned |
98
+ | `@Controller('users')` | `@controller(prefix="/users", tags=["users"])` |
99
+ | `@Get()` `@Post()` `@Patch()` `@Delete()` | `@get()` `@post()` `@patch()` `@delete()` |
100
+ | `@Injectable()` | `@injectable` |
101
+ | `@Injectable({scope: Scope.REQUEST})` | `@injectable(scope=Scope.REQUEST)` |
102
+ | `forwardRef(() => X)` | `Lazy[X]` |
103
+ | `@InjectRepository(X) repo: Repository<X>` | `repo: Repository[X]` |
104
+ | `@UseGuards()` | `guards=[...]` on the controller or a single route |
105
+ | `@WebSocketGateway()` | `@gateway(path="/ws/…")` |
106
+ | `@SubscribeMessage('x')` | `@subscribe("x")` |
107
+ | `@EventPattern('x')` (RabbitMQ) | `@rabbitmq_subscriber("events", "x", queue="…")` |
108
+ | `CacheModule` / `CACHE_MANAGER` | `RedisClient.cached(key, factory, ttl=…)` |
109
+ | socket.io Redis adapter | `APP_WS__ADAPTER=redis` |
110
+
111
+ Full side-by-side table in
112
+ [docs/architecture.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/architecture.md).
113
+
114
+ ## Getting started
115
+
116
+ Requires **Python 3.10+**.
117
+
118
+ ```bash
119
+ python3 -m venv .venv && . .venv/bin/activate
120
+ pip install fastapi-modular
121
+
122
+ fam init # scaffolds into the CURRENT directory, no extra nesting
123
+ fam dev
124
+ ```
125
+
126
+ Open http://localhost:8000/docs — a working `health` module is already there.
127
+
128
+ `fam init` takes the project name from the current directory name; use
129
+ `fam init --name other-name` to override. It never overwrites an existing file,
130
+ so it is safe to run inside a directory that already has code. If you want it to
131
+ create the directory for you, use `fam new <name>`.
132
+
133
+ The core pulls in **no** database driver and **no** queue client. Add only what
134
+ you need:
135
+
136
+ ```bash
137
+ fam install sqlite # or postgres, mongodb
138
+ fam install rabbitmq # or redis, mqtt, kafka
139
+ fam install all # everything above
140
+ ```
141
+
142
+ `fam install` both installs the libraries and writes the matching variables into
143
+ `.env`. Plain pip works too: `pip install "fastapi-modular[sqlite,rabbitmq]"`.
144
+
145
+ ## Commands
146
+
147
+ One program, two names: `fastapi-modular` (full) and `fam` (short). Examples use
148
+ `fam`.
149
+
150
+ Command names can be abbreviated as long as the prefix is unambiguous — `fam mo
151
+ alerts` is exactly `fam module alerts`. When ambiguous, it asks instead of
152
+ guessing:
153
+
154
+ ```
155
+ $ fam m
156
+ fam: lệnh 'm' chưa rõ — khớp với migrate, module. Gõ thêm vài chữ cho rõ.
157
+ ```
158
+
159
+ | Command | Short | What it does |
160
+ |---|---|---|
161
+ | `fam init [--name <n>]` | `fam ini` | scaffold **into the current directory**; never overwrites; name defaults to the directory name |
162
+ | `fam new <name>` | `fam n` | scaffold into a new directory |
163
+ | `fam dev` | `fam d` | run with autoreload |
164
+ | `fam run --workers 4` | `fam r` | run in production mode |
165
+ | `fam module <name>` | `fam mo` | generate a module: controller + service + dto + entity |
166
+ | `fam module <name> --gateway` | | plus a WebSocket gateway (`--consumer` for RabbitMQ) |
167
+ | `fam module <name> --gateway-only` | | add a gateway to an **existing** module (`--consumer-only` for RabbitMQ) |
168
+ | `fam module <name> --entity <N>` | | set the entity class name; guessed from the module name otherwise |
169
+ | `fam env <component>` | `fam e` | only write config variables into `.env` (installs nothing) |
170
+ | `fam clean` | `fam c` | remove caches and build output (leaves `data/` alone) |
171
+ | `fam build` · `fam publish [--test]` | `fam b` · `fam p` | build wheel/sdist · upload to PyPI |
172
+ | `fam info` | `fam inf` | what it connects to, what is installed, production config warnings |
173
+ | `fam migrate [up\|down\|history\|sql\|create]` | `fam mi` | Alembic |
174
+ | `fam test` · `fam lint [--fix]` | `fam t` · `fam l` | pytest · ruff. Bare `fam lint` checks `src`; pass paths to check elsewhere |
175
+ | **Databases** | | *installs libraries **then** writes `.env`* |
176
+ | `fam install sqlite` | `fam ins s` | a `.db` file, no server needed |
177
+ | `fam install postgres` | `fam ins p` | PostgreSQL |
178
+ | `fam install mongodb` | `fam ins mo` | MongoDB |
179
+ | **Queues** | | *installs libraries **then** writes `.env`* |
180
+ | `fam install rabbitmq` | `fam ins ra` | durable queues, retry + DLQ |
181
+ | `fam install redis` | `fam ins re` | cache, atomic counters, pub/sub |
182
+ | `fam install mqtt` | `fam ins mq` | IoT devices |
183
+ | `fam install kafka` | `fam ins k` | replayable event log |
184
+ | `fam install ws-redis` | `fam ins w` | WebSocket broadcast across workers |
185
+ | `fam install dev` | `fam ins d` | pytest · pytest-asyncio · httpx · ruff |
186
+ | `fam install all` | `fam ins a` | everything above **except** `dev` |
187
+
188
+ Host and port come from `APP_HOST` / `APP_PORT` in `.env`, so `fam dev` needs no
189
+ arguments. `fam --help` lists everything.
190
+
191
+ ## Adding a module
192
+
193
+ ```bash
194
+ fam module alerts # controller + service + dto + entities
195
+ fam module alerts --gateway # plus a WebSocket gateway
196
+ fam module alerts --consumer # plus a RabbitMQ consumer
197
+ ```
198
+
199
+ Routes appear immediately, the table is created, validation runs — only the
200
+ method bodies are missing (calling them returns 501 with the function name). Your
201
+ job: add fields to the entity and the DTO, then write the service bodies.
202
+
203
+ Nothing else to edit — no registration step. Details:
204
+ [docs/architecture.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/architecture.md#thêm-module-mới).
205
+
206
+ ## Choosing a database
207
+
208
+ One shared `Repository[T]` over **memory, SQLite, PostgreSQL and MongoDB** —
209
+ switching the backend does not change your service code.
210
+
211
+ ```bash
212
+ fam install sqlite # or postgres, mongodb
213
+ fam env sqlite # write .env only, install nothing
214
+ fam info # what it is connected to right now
215
+ ```
216
+
217
+ Details:
218
+ [docs/database.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/database.md).
219
+
220
+ ## Your own configuration
221
+
222
+ Subclass `Settings` and the new variables are readable from `.env` — no framework
223
+ file to edit:
224
+
225
+ ```python
226
+ # src/core/config.py — generated by fam init
227
+ class AppSettings(Settings):
228
+ team_name: str = Field(default="", alias="APP_TEAM_NAME")
229
+ jwt: JwtSettings = Field(default_factory=JwtSettings, alias="APP_JWT") # -> APP_JWT__SECRET
230
+ ```
231
+
232
+ Services receive `AppSettings` through DI with full type hints. Details:
233
+ [docs/config.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/config.md).
234
+
235
+ ## The entry point is your file
236
+
237
+ `fam init` generates `src/main.py` with every assembly step spelled out — add
238
+ middleware, change CORS, mount a third-party router right there:
239
+
240
+ ```python
241
+ settings = bind_settings(AppSettings())
242
+ configure_logging(settings.log)
243
+
244
+ app = new_fastapi(settings, lifespan=lifespan)
245
+ add_middleware(app, settings) # CORS + request-id + access log
246
+ register_error_handlers(app, debug=settings.debug)
247
+ register_routes(app, prefix=settings.api_prefix) # scans src/api/
248
+ ```
249
+
250
+ If you need none of that, the whole block collapses to
251
+ `app = create_app(AppSettings())` — `create_app` runs exactly that sequence,
252
+ nothing more.
253
+
254
+ Lifespan works the same way: `src/core/lifespan.py` is yours, and it simply
255
+ **wraps** the framework's infrastructure:
256
+
257
+ ```python
258
+ @asynccontextmanager
259
+ async def lifespan(app):
260
+ async with framework_lifespan(app): # framework opens database, queues
261
+ await warm_cache() # your work — the database is ready
262
+ try:
263
+ yield
264
+ finally:
265
+ await flush_ledger() # your work — the database is STILL up
266
+ ```
267
+
268
+ ## Realtime (WebSocket)
269
+
270
+ One connection per client; join **rooms** for group messages, or receive messages
271
+ addressed to you alone:
272
+
273
+ ```python
274
+ @gateway(path="/ws/alerts", guards=[WsJwt], client_rooms=True)
275
+ class AlertGateway:
276
+ @subscribe("alert.ack")
277
+ async def ack(self, socket: Socket, payload: AlertAck) -> dict:
278
+ return {"ok": True}
279
+ ```
280
+
281
+ ```bash
282
+ fam dev
283
+ # ws://localhost:8000/ws/chat?client_id=an
284
+
285
+ fam module alerts --gateway-only # add a gateway to an existing module
286
+ fam install ws-redis # required when running multiple workers
287
+ ```
288
+
289
+ To push from REST or a background task, take `WebSocketServer` in `__init__` and
290
+ call `to_room` / `to_user` / `to_socket`.
291
+
292
+ Full guide — including **Postman** and a **Next.js** client, plus the four things
293
+ every client must do:
294
+ [docs/websocket.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/websocket.md).
295
+
296
+ ## Queues (RabbitMQ — optional)
297
+
298
+ ```python
299
+ await self._mq.publish("events", "alert.created.hanoi", {"id": "A1"})
300
+
301
+ # Default: exactly ONE queue on the broker; failures are dropped (and logged).
302
+ @rabbitmq_subscriber("events", "alert.created", queue="alert-mailer")
303
+ async def send_mail(self, payload: AlertCreated) -> None: ...
304
+
305
+ # Opt in when the message is worth money -> adds alert-mailer.retry and .dlq
306
+ @rabbitmq_subscriber("events", "alert.created", queue="alert-mailer",
307
+ max_retries=3, dead_letter=True)
308
+ async def send_mail(self, payload: AlertCreated) -> None: ...
309
+ ```
310
+
311
+ Not installed and not enabled means it behaves as if it never existed. If the
312
+ broker goes down the app keeps serving and reconnects on its own. Details:
313
+ [docs/rabbitmq.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/rabbitmq.md).
314
+
315
+ ## Redis, MQTT, Kafka (also optional)
316
+
317
+ Same shape as RabbitMQ: one package under `infrastructure/`, one `APP_<NAME>__*`
318
+ variable group, **off** by default, the library is imported only when enabled, and
319
+ all of them reconnect automatically.
320
+
321
+ ```python
322
+ await redis.cached("report:A", compute, ttl=30) # miss = compute, hit = skip
323
+ await mqtt.publish("devices/kitchen/light", "ON", qos=1, retain=True)
324
+ await kafka.publish("orders", order, key=order.id) # same key = same order
325
+
326
+ @redis_subscriber("price:*") # Redis: every worker gets a copy
327
+ @mqtt_subscriber("devices/+/temperature", qos=1) # MQTT: + one level, # all levels
328
+ @kafka_subscriber("orders", group="warehouse") # Kafka: one cursor per group
329
+ ```
330
+
331
+ | You need | Use |
332
+ |---|---|
333
+ | messages must not be lost, work split across workers | RabbitMQ |
334
+ | fast, every worker gets a copy, losing a few is fine | Redis |
335
+ | devices, flaky networks, long-lived connections | MQTT |
336
+ | replayable history, several independent reader groups | Kafka |
337
+
338
+ ## Operations
339
+
340
+ ```bash
341
+ curl localhost:8000/api/health # liveness
342
+ curl localhost:8000/api/health/ready # readiness, pings the database
343
+ curl localhost:8000/api/metrics # Prometheus metrics
344
+ fam migrate # run migrations (SQL)
345
+ fam info # current config + production warnings
346
+ ```
347
+
348
+ Guards, circuit breaker, metrics and tracing:
349
+ [docs/operations.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/operations.md).
350
+
351
+ ## Layout of this repository
352
+
353
+ ```
354
+ fastapi_modular/ THE LIBRARY — what gets packaged and installed
355
+ core/ DI, controllers, config, WebSocket, guards, metrics
356
+ infrastructure/ database, rabbitmq, redis, mqtt, kafka (one package each)
357
+ cli/ init · new · module · dev · run · install · env · info
358
+ migrate · test · lint · clean · build · publish
359
+ factory.py create_app()
360
+ discovery.py scans the application package and builds routers
361
+ src/ SAMPLE APPLICATION — not shipped in the package; delete freely
362
+ main.py entry point: assembles the app — your file, not the framework's
363
+ core/config.py AppSettings: subclass Settings to add your own .env variables
364
+ core/lifespan.py application-specific startup / shutdown work
365
+ api/ business modules; every subdirectory is one module
366
+ tests/ 341 tests that need no infrastructure, 40 more when servers exist
367
+ docs/ reference documentation (Vietnamese)
368
+ ```
369
+
370
+ `fastapi_modular/` imports nothing from `src/`. All it knows is "there is a
371
+ package called `src.api`, go scan it" — so a different layout is fine, declared
372
+ once in `src/main.py`: `register_routes(app, package="company.service")`.
373
+
374
+ ## Contributing
375
+
376
+ ```bash
377
+ git clone git@github.com:quanglinh2909/fastapi-modular.git && cd fastapi-modular
378
+ pip install -e ".[all,dev]"
379
+ fam dev # runs the sample app in src/
380
+ fam test
381
+ fam lint fastapi_modular src tests
382
+ ```
383
+
384
+ Tests that need real infrastructure only run when the matching environment
385
+ variable is set:
386
+
387
+ ```bash
388
+ docker run -d -p 6379:6379 redis:7-alpine
389
+ TEST_REDIS_URL=redis://localhost:6379/0 fam test
390
+ ```
391
+
392
+ See the top of each `tests/test_<name>.py` for the Docker command and the
393
+ variables it needs.
394
+
395
+ ## License
396
+
397
+ MIT — see [LICENSE](https://github.com/quanglinh2909/fastapi-modular/blob/main/LICENSE).
398
+
399
+ ## Documentation
400
+
401
+ Written in Vietnamese, organised for reference rather than reading front to back.
402
+
403
+ - [docs/architecture.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/architecture.md) — module layout, DI, the NestJS comparison
404
+ - [docs/config.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/config.md) — Settings, precedence, adding your own variables
405
+ - [docs/database.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/database.md) — memory / SQLite / PostgreSQL / MongoDB
406
+ - [docs/migrations.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/migrations.md) — Alembic: generate, run, roll back
407
+ - [docs/websocket.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/websocket.md) — WebSocket gateway, rooms, Postman, Next.js
408
+ - [docs/rabbitmq.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/rabbitmq.md) — exchanges, topics, background consumers, `.retry` / `.dlq`
409
+ - [docs/redis.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/redis.md) — cache, atomic counters, pub/sub
410
+ - [docs/mqtt.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/mqtt.md) — QoS, retain, `+` and `#` topic matching
411
+ - [docs/kafka.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/kafka.md) — consumer groups, partitions, `.dlt`
412
+ - [docs/operations.md](https://github.com/quanglinh2909/fastapi-modular/blob/main/docs/operations.md) — guards, circuit breaker, metrics, tracing