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.
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/CHANGELOG.md +18 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/LICENSE +1 -1
- fastapi_modular-0.2.1/PKG-INFO +412 -0
- fastapi_modular-0.2.1/README.md +342 -0
- fastapi_modular-0.2.0/README.md → fastapi_modular-0.2.1/README.vi.md +31 -6
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/README.md +1 -1
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/operations.md +2 -2
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/rabbitmq.md +1 -1
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/websocket.md +368 -223
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/__init__.py +1 -1
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/pyproject.toml +19 -5
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_settings_mo_rong.py +2 -2
- fastapi_modular-0.2.0/PKG-INFO +0 -377
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/.gitignore +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/Makefile +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/alembic.ini +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/architecture.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/config.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/database.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/kafka.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/migrations.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/mqtt.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/docs/redis.md +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/clean.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/configure_env.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/cong_cu.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/info.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/install.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/main.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/new_module.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/new_project.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/cli/serve.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/clock.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/compat.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/config.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/container.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/context.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/error_handlers.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/exceptions.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/guards.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/lifespan.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/logging.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/schemas.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/adapter.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/gateway.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/namespace.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/protocol.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/server.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/core/websocket/socket.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/discovery.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/factory.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/base.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/circuit.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/factory.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/memory.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/mongo.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/repository.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/database/sql.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/broker.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/consumers.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/kafka/metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/client.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/consumers.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/mqtt/patterns.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/broker.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/consumers.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/rabbitmq/patterns.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/client.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/infrastructure/redis/pubsub.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/middleware/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/middleware/request_context.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/fastapi_modular/py.typed +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/env.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/script.py.mako +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/versions/.gitkeep +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/migrations/versions/20260821_1020_tao_bang_users_va_devices.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/pytest.ini +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/ruff.toml +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/chat_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/chat_gateway.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/dto/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/chat/dto/chat_dto.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/device_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/device_service.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/dto/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/dto/device_dto.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/entities/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/devices/entities/device_model.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/health/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/health/health_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/kafka_consumer.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/kafka_test/kafka_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/metrics/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/metrics/metrics_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/mqtt_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/mqtt_test/mqtt_listener.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/rabbitmq_consumer.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/rabbitmq_test/rabbitmq_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/redis_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/redis_test/redis_listener.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/dto/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/dto/user_dto.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/entities/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/entities/user_model.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/user_controller.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/api/users/user_service.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/__init__.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/config.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/core/lifespan.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/src/main.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/conftest.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_circuit.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_cli.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_configure_env.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_container.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_cross_module.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_database.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_drivers.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_guards.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_ha_tang_that.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_health.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_kafka.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_kafka_offline.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_lifespan_rieng.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_metrics.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_module_generator.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_mqtt.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_mqtt_offline.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_rabbitmq.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_rabbitmq_offline.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_redis.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_redis_offline.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_resilience.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_schema_evolution.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_schemas.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_tuong_thich_phien_ban.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_uniqueness.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_users_api.py +0 -0
- {fastapi_modular-0.2.0 → fastapi_modular-0.2.1}/tests/test_websocket.py +0 -0
- {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
|
|
@@ -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
|