fastapi-basekit 0.3.0__tar.gz → 0.3.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 (114) hide show
  1. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/PKG-INFO +23 -19
  2. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/README.md +16 -10
  3. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/repository/base.py +29 -5
  4. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/__init__.py +2 -1
  5. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/service/base.py +8 -1
  6. fastapi_basekit-0.3.1/fastapi_basekit/aio/sqlalchemy/session.py +67 -0
  7. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/config/database.py +7 -20
  8. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/PKG-INFO +23 -19
  9. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/SOURCES.txt +1 -0
  10. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/requires.txt +6 -8
  11. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/pyproject.toml +7 -9
  12. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/LICENSE +0 -0
  13. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/__init__.py +0 -0
  14. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/__init__.py +0 -0
  15. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/__init__.py +0 -0
  16. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/controller/__init__.py +0 -0
  17. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/controller/base.py +0 -0
  18. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/repository/__init__.py +0 -0
  19. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/service/__init__.py +0 -0
  20. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/beanie/service/base.py +0 -0
  21. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/controller/__init__.py +0 -0
  22. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/controller/base.py +0 -0
  23. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/permissions/__init__.py +0 -0
  24. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/permissions/base.py +0 -0
  25. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/controller/__init__.py +0 -0
  26. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/controller/base.py +0 -0
  27. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/repository/__init__.py +0 -0
  28. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/repository/base.py +0 -0
  29. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlalchemy/service/__init__.py +0 -0
  30. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/__init__.py +0 -0
  31. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/controller/__init__.py +0 -0
  32. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/controller/base.py +0 -0
  33. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/repository/__init__.py +0 -0
  34. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/repository/base.py +0 -0
  35. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/service/__init__.py +0 -0
  36. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/aio/sqlmodel/service/base.py +0 -0
  37. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/cli/__init__.py +0 -0
  38. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/cli/main.py +0 -0
  39. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/exceptions/__init__.py +0 -0
  40. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/exceptions/api_exceptions.py +0 -0
  41. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/exceptions/handler.py +0 -0
  42. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/schema/__init__.py +0 -0
  43. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/schema/base.py +0 -0
  44. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/schema/jwt.py +0 -0
  45. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/schema/schema.py +0 -0
  46. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/servicios/__init__.py +0 -0
  47. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/servicios/thrid/__init__.py +0 -0
  48. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/servicios/thrid/jwt.py +0 -0
  49. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/cookiecutter.json +0 -0
  50. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/hooks/post_gen_project.py +0 -0
  51. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/hooks/pre_gen_project.py +0 -0
  52. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/.env.example +0 -0
  53. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/.gitignore +0 -0
  54. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/Dockerfile +0 -0
  55. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/LICENSE +0 -0
  56. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/Makefile +0 -0
  57. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/README.md +0 -0
  58. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/alembic/env.py +0 -0
  59. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/alembic/script.py.mako +0 -0
  60. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/alembic.ini +0 -0
  61. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/__init__.py +0 -0
  62. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/__init__.py +0 -0
  63. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/__init__.py +0 -0
  64. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/endpoints/__init__.py +0 -0
  65. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/endpoints/auth/__init__.py +0 -0
  66. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/endpoints/auth/auth.py +0 -0
  67. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/endpoints/user/__init__.py +0 -0
  68. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/endpoints/user/user.py +0 -0
  69. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/api/v1/routers.py +0 -0
  70. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/config/__init__.py +0 -0
  71. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/config/settings.py +0 -0
  72. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/main.py +0 -0
  73. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/middleware/__init__.py +0 -0
  74. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/middleware/auth.py +0 -0
  75. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/middleware/permissions.py +0 -0
  76. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/models/__init__.py +0 -0
  77. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/models/auth.py +0 -0
  78. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/models/base.py +0 -0
  79. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/models/enums.py +0 -0
  80. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/models/types.py +0 -0
  81. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/permissions/__init__.py +0 -0
  82. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/permissions/user.py +0 -0
  83. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/repositories/__init__.py +0 -0
  84. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/repositories/user/__init__.py +0 -0
  85. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/repositories/user/repository.py +0 -0
  86. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/schemas/__init__.py +0 -0
  87. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/schemas/auth.py +0 -0
  88. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/schemas/base.py +0 -0
  89. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/schemas/user.py +0 -0
  90. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/scripts/__init__.py +0 -0
  91. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/scripts/init.py +0 -0
  92. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/scripts/init_admin.py +0 -0
  93. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/services/__init__.py +0 -0
  94. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/services/auth_service.py +0 -0
  95. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/services/dependency.py +0 -0
  96. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/services/user_service.py +0 -0
  97. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/utils/__init__.py +0 -0
  98. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/utils/exception_handlers.py +0 -0
  99. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/app/utils/security.py +0 -0
  100. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/docker-compose.yml +0 -0
  101. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/pytest.ini +0 -0
  102. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit/templates/project/{{cookiecutter.project_slug}}/requirements.txt +0 -0
  103. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/dependency_links.txt +0 -0
  104. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/entry_points.txt +0 -0
  105. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/fastapi_basekit.egg-info/top_level.txt +0 -0
  106. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/setup.cfg +0 -0
  107. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_api_exceptions.py +0 -0
  108. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_base_response.py +0 -0
  109. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_base_service.py +0 -0
  110. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_controller_auto_permissions.py +0 -0
  111. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_crud_beanie_controller.py +0 -0
  112. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_crud_controller.py +0 -0
  113. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_jwt_service.py +0 -0
  114. {fastapi_basekit-0.3.0 → fastapi_basekit-0.3.1}/tests/test_sqlalchemy_base_service_order.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-basekit
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Utilities and base classes for FastAPI async projects (Beanie, SQLAlchemy or SQLModel)
5
5
  Author-email: Jerson Moreno <jerson.ml820@hotmail.com>
6
6
  License: MIT
@@ -16,14 +16,13 @@ Requires-Python: >=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: fastapi>=0.116.1
19
- Requires-Dist: pydantic<3,>=2.11.7
19
+ Requires-Dist: pydantic<3,>=2.13.0
20
20
  Requires-Dist: fastapi-restful[all]>=0.6.0
21
- Requires-Dist: pyjwt>=2.10.1
21
+ Requires-Dist: pyjwt>=2.12.1
22
22
  Provides-Extra: beanie
23
- Requires-Dist: beanie>=1.24.0; extra == "beanie"
24
- Requires-Dist: motor>=3.3.0; extra == "beanie"
23
+ Requires-Dist: beanie<3,>=2.0; extra == "beanie"
25
24
  Provides-Extra: sqlalchemy
26
- Requires-Dist: SQLAlchemy[asyncio]>=2.0.0; extra == "sqlalchemy"
25
+ Requires-Dist: SQLAlchemy[asyncio]<3,>=2.0.30; extra == "sqlalchemy"
27
26
  Requires-Dist: psycopg2>=2.9.0; extra == "sqlalchemy"
28
27
  Provides-Extra: sqlmodel
29
28
  Requires-Dist: sqlmodel>=0.0.37; extra == "sqlmodel"
@@ -36,9 +35,8 @@ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == "docs"
36
35
  Requires-Dist: pymdown-extensions>=10.10; extra == "docs"
37
36
  Requires-Dist: mike>=2.1.0; extra == "docs"
38
37
  Provides-Extra: all
39
- Requires-Dist: beanie>=1.24.0; extra == "all"
40
- Requires-Dist: motor>=3.3.0; extra == "all"
41
- Requires-Dist: SQLAlchemy[asyncio]>=2.0.0; extra == "all"
38
+ Requires-Dist: beanie<3,>=2.0; extra == "all"
39
+ Requires-Dist: SQLAlchemy[asyncio]<3,>=2.0.30; extra == "all"
42
40
  Requires-Dist: psycopg2>=2.9.0; extra == "all"
43
41
  Requires-Dist: sqlmodel>=0.0.37; extra == "all"
44
42
  Requires-Dist: cookiecutter>=2.5.0; extra == "all"
@@ -48,18 +46,24 @@ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == "all"
48
46
 
49
47
  <div align="center">
50
48
 
51
- # FastAPI BaseKit
49
+ <img src="docs/assets/logo-mark.svg" width="120" alt="fastapi-basekit">
52
50
 
53
- **Toolkit base para construir APIs FastAPI rápido — sin reinventar repos, services y controllers.**
51
+ # fastapi-basekit
54
52
 
55
- [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=teal)](https://pypi.org/project/fastapi-basekit/)
56
- ![Python](https://img.shields.io/badge/python-3.11+-blue?style=flat-square&logo=python)
57
- ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi)
58
- ![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-red?style=flat-square)
59
- ![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb)
60
- ![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)
53
+ **FastAPI toolkit con repos, services y controllers listos para producción.**
54
+ **Multi-ORM · CLI scaffolder · plugin Claude Code.**
61
55
 
62
- [**Docs**](https://mundobien2025.github.io/fastapi-basekit) · [**PyPI**](https://pypi.org/project/fastapi-basekit/) · [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) · [**Changelog**](./CHANGELOG.md)
56
+ [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=009485&logo=pypi&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
57
+ [![Python](https://img.shields.io/badge/python-3.11+-2c5282?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
58
+ [![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
59
+ [![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-c41616?style=flat-square)](https://www.sqlalchemy.org/)
60
+ [![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb&logoColor=white)](https://beanie-odm.dev/)
61
+ [![License](https://img.shields.io/badge/license-MIT-009485?style=flat-square)](./LICENSE)
62
+
63
+ [**Docs**](https://mundobien2025.github.io/fastapi-basekit) ·
64
+ [**PyPI**](https://pypi.org/project/fastapi-basekit/) ·
65
+ [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) ·
66
+ [**Changelog**](./CHANGELOG.md)
63
67
 
64
68
  </div>
65
69
 
@@ -89,7 +93,7 @@ Abre http://localhost:8000/docs. Login con `admin@example.com` / `ChangeMe2026!`
89
93
 
90
94
  ## Documentación
91
95
 
92
- 📚 **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
96
+ **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
93
97
 
94
98
  | Sección | Contenido |
95
99
  |---|---|
@@ -1,17 +1,23 @@
1
1
  <div align="center">
2
2
 
3
- # FastAPI BaseKit
3
+ <img src="docs/assets/logo-mark.svg" width="120" alt="fastapi-basekit">
4
4
 
5
- **Toolkit base para construir APIs FastAPI rápido — sin reinventar repos, services y controllers.**
5
+ # fastapi-basekit
6
6
 
7
- [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=teal)](https://pypi.org/project/fastapi-basekit/)
8
- ![Python](https://img.shields.io/badge/python-3.11+-blue?style=flat-square&logo=python)
9
- ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi)
10
- ![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-red?style=flat-square)
11
- ![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb)
12
- ![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)
7
+ **FastAPI toolkit con repos, services y controllers listos para producción.**
8
+ **Multi-ORM · CLI scaffolder · plugin Claude Code.**
13
9
 
14
- [**Docs**](https://mundobien2025.github.io/fastapi-basekit) · [**PyPI**](https://pypi.org/project/fastapi-basekit/) · [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) · [**Changelog**](./CHANGELOG.md)
10
+ [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=009485&logo=pypi&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
11
+ [![Python](https://img.shields.io/badge/python-3.11+-2c5282?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
12
+ [![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
13
+ [![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-c41616?style=flat-square)](https://www.sqlalchemy.org/)
14
+ [![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb&logoColor=white)](https://beanie-odm.dev/)
15
+ [![License](https://img.shields.io/badge/license-MIT-009485?style=flat-square)](./LICENSE)
16
+
17
+ [**Docs**](https://mundobien2025.github.io/fastapi-basekit) ·
18
+ [**PyPI**](https://pypi.org/project/fastapi-basekit/) ·
19
+ [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) ·
20
+ [**Changelog**](./CHANGELOG.md)
15
21
 
16
22
  </div>
17
23
 
@@ -41,7 +47,7 @@ Abre http://localhost:8000/docs. Login con `admin@example.com` / `ChangeMe2026!`
41
47
 
42
48
  ## Documentación
43
49
 
44
- 📚 **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
50
+ **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
45
51
 
46
52
  | Sección | Contenido |
47
53
  |---|---|
@@ -2,9 +2,9 @@ from typing import Any, Dict, List, Optional, Type, Union
2
2
  from typing import get_args, get_origin
3
3
  import re
4
4
 
5
- from bson import ObjectId, Link
5
+ from bson import ObjectId
6
6
  from pydantic import BaseModel
7
- from beanie import Document
7
+ from beanie import Document, Link
8
8
  from beanie.odm.queries.find import FindMany
9
9
  from beanie.operators import Or, RegEx
10
10
 
@@ -154,18 +154,42 @@ class BaseRepository:
154
154
 
155
155
  raw_filters: Dict[str, Any] = {}
156
156
 
157
+ def _coerce_objectid(value: Any) -> Any:
158
+ """str/UUID → ObjectId para queries Mongo sobre Link.id."""
159
+ if isinstance(value, ObjectId):
160
+ return value
161
+ if isinstance(value, str):
162
+ try:
163
+ return ObjectId(value)
164
+ except Exception:
165
+ return value
166
+ return value
167
+
157
168
  for k, v in (filters or {}).items():
158
169
  # MongoDB-style keys (dot-notation like "user.$id" or operators like "$or")
159
170
  # cannot be resolved via hasattr — pass them as a raw dict to find()
160
171
  if "." in k or k.startswith("$"):
161
172
  raw_filters[k] = v
162
- elif hasattr(self.model, k):
163
- field_attr = getattr(self.model, k)
173
+ continue
164
174
 
175
+ if hasattr(self.model, k):
176
+ field_attr = getattr(self.model, k)
165
177
  if _is_link_field(k):
166
- exprs.append(field_attr.id == v)
178
+ exprs.append(field_attr.id == _coerce_objectid(v))
167
179
  else:
168
180
  exprs.append(field_attr == v)
181
+ continue
182
+
183
+ # `<field>_id` alias para Link fields. Permite filtros con
184
+ # `customer_id`, `user_id`, etc. sin que el caller deba conocer
185
+ # la sintaxis Mongo nested. Sólo se activa si <field> existe en
186
+ # el modelo y es un Link[X].
187
+ if k.endswith("_id"):
188
+ base = k[:-3]
189
+ if hasattr(self.model, base) and _is_link_field(base):
190
+ field_attr = getattr(self.model, base)
191
+ exprs.append(field_attr.id == _coerce_objectid(v))
192
+ continue
169
193
 
170
194
  # Raw MongoDB filters go first so Beanie processes them as a dict condition
171
195
  query_args: list = ([raw_filters] if raw_filters else []) + exprs
@@ -1,6 +1,7 @@
1
- __all__ = ["repository", "service", "controller"]
2
1
  from .controller.base import SQLAlchemyBaseController
2
+ from .session import make_session_lifecycle
3
3
 
4
4
  __all__ = [
5
5
  "SQLAlchemyBaseController",
6
+ "make_session_lifecycle",
6
7
  ]
@@ -10,7 +10,14 @@ from ....exceptions.api_exceptions import (
10
10
 
11
11
 
12
12
  class BaseService:
13
- """Servicio base para SQLAlchemy AsyncSession."""
13
+ """Servicio base para SQLAlchemy AsyncSession.
14
+
15
+ Regla del proyecto: los servicios NO deben llamar `session.flush()`,
16
+ `session.commit()` ni `session.refresh()`. El flush vive en
17
+ `BaseRepository.create / update`; el commit/rollback único por
18
+ request lo gestiona el lifecycle creado con
19
+ `fastapi_basekit.aio.sqlalchemy.make_session_lifecycle`.
20
+ """
14
21
 
15
22
  repository: BaseRepository
16
23
  search_fields: List[str] = []
@@ -0,0 +1,67 @@
1
+ """Reusable async SQLAlchemy session lifecycle.
2
+
3
+ Single commit / single rollback per request. Optional hooks fire after
4
+ commit (success) or rollback (error) so callers can attach logging,
5
+ metrics, sentry, retries, etc. without coupling the lifecycle to any
6
+ specific telemetry stack.
7
+
8
+ Usage:
9
+
10
+ from fastapi_basekit.aio.sqlalchemy.session import make_session_lifecycle
11
+ from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
12
+
13
+ engine = create_async_engine(DATABASE_URL)
14
+ SessionFactory = async_sessionmaker(engine, autoflush=False, expire_on_commit=False)
15
+
16
+ async def on_error(exc, session):
17
+ logger.exception("rollback", exc_info=exc)
18
+
19
+ get_db = make_session_lifecycle(SessionFactory, on_error=on_error)
20
+
21
+ # then in routes: ... session: AsyncSession = Depends(get_db)
22
+
23
+ Rule of thumb for callers:
24
+ - Services SHOULD NOT call session.flush / session.commit / session.refresh.
25
+ - Repositories own flush via BaseRepository.create / update.
26
+ - get_db owns the single commit (success) and rollback (error).
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ from collections.abc import AsyncGenerator, Awaitable, Callable
32
+ from typing import Optional
33
+
34
+ from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
35
+
36
+ ErrorHook = Callable[[Exception, AsyncSession], Awaitable[None]]
37
+ SuccessHook = Callable[[AsyncSession], Awaitable[None]]
38
+
39
+
40
+ def make_session_lifecycle(
41
+ session_factory: async_sessionmaker[AsyncSession],
42
+ *,
43
+ on_success: Optional[SuccessHook] = None,
44
+ on_error: Optional[ErrorHook] = None,
45
+ ) -> Callable[[], AsyncGenerator[AsyncSession, None]]:
46
+ """Return an async generator dependency that owns the request session.
47
+
48
+ The returned callable yields a session, commits on success, rolls back
49
+ on error, and invokes optional hooks. Hooks must not raise — wrap them
50
+ in try/except at the call site if their failure should not poison the
51
+ request.
52
+ """
53
+
54
+ async def get_db() -> AsyncGenerator[AsyncSession, None]:
55
+ async with session_factory() as session:
56
+ try:
57
+ yield session
58
+ await session.commit()
59
+ if on_success is not None:
60
+ await on_success(session)
61
+ except Exception as exc:
62
+ await session.rollback()
63
+ if on_error is not None:
64
+ await on_error(exc, session)
65
+ raise
66
+
67
+ return get_db
@@ -2,15 +2,11 @@
2
2
  {% if cookiecutter.orm == "sqlalchemy" %}
3
3
  import os
4
4
  import sys
5
- from collections.abc import AsyncGenerator
6
5
  from contextlib import asynccontextmanager
7
6
 
8
7
  from fastapi import FastAPI
9
- from sqlalchemy.ext.asyncio import (
10
- AsyncSession,
11
- async_sessionmaker,
12
- create_async_engine,
13
- )
8
+ from fastapi_basekit.aio.sqlalchemy import make_session_lifecycle
9
+ from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
14
10
  from sqlalchemy.pool import NullPool
15
11
 
16
12
  from app.config.settings import get_settings
@@ -43,20 +39,11 @@ AsyncSessionFactory = async_sessionmaker(
43
39
  expire_on_commit=False,
44
40
  )
45
41
 
46
-
47
- async def get_db() -> AsyncGenerator[AsyncSession, None]:
48
- """Yield a session, commit on success, rollback + reraise on error.
49
-
50
- Domain-specific error translation lives in `app/utils/exception_handlers.py`,
51
- registered globally in `main.py`. This generator only manages session lifecycle.
52
- """
53
- async with AsyncSessionFactory() as session:
54
- try:
55
- yield session
56
- await session.commit()
57
- except Exception:
58
- await session.rollback()
59
- raise
42
+ # Single commit/rollback per request. Wire on_error / on_success hooks
43
+ # here for logging, sentry, metrics, etc. — services must NOT call
44
+ # session.flush / session.commit / session.refresh; repos own flush
45
+ # via BaseRepository.create / update.
46
+ get_db = make_session_lifecycle(AsyncSessionFactory)
60
47
 
61
48
 
62
49
  async def init_db():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-basekit
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Utilities and base classes for FastAPI async projects (Beanie, SQLAlchemy or SQLModel)
5
5
  Author-email: Jerson Moreno <jerson.ml820@hotmail.com>
6
6
  License: MIT
@@ -16,14 +16,13 @@ Requires-Python: >=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Requires-Dist: fastapi>=0.116.1
19
- Requires-Dist: pydantic<3,>=2.11.7
19
+ Requires-Dist: pydantic<3,>=2.13.0
20
20
  Requires-Dist: fastapi-restful[all]>=0.6.0
21
- Requires-Dist: pyjwt>=2.10.1
21
+ Requires-Dist: pyjwt>=2.12.1
22
22
  Provides-Extra: beanie
23
- Requires-Dist: beanie>=1.24.0; extra == "beanie"
24
- Requires-Dist: motor>=3.3.0; extra == "beanie"
23
+ Requires-Dist: beanie<3,>=2.0; extra == "beanie"
25
24
  Provides-Extra: sqlalchemy
26
- Requires-Dist: SQLAlchemy[asyncio]>=2.0.0; extra == "sqlalchemy"
25
+ Requires-Dist: SQLAlchemy[asyncio]<3,>=2.0.30; extra == "sqlalchemy"
27
26
  Requires-Dist: psycopg2>=2.9.0; extra == "sqlalchemy"
28
27
  Provides-Extra: sqlmodel
29
28
  Requires-Dist: sqlmodel>=0.0.37; extra == "sqlmodel"
@@ -36,9 +35,8 @@ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == "docs"
36
35
  Requires-Dist: pymdown-extensions>=10.10; extra == "docs"
37
36
  Requires-Dist: mike>=2.1.0; extra == "docs"
38
37
  Provides-Extra: all
39
- Requires-Dist: beanie>=1.24.0; extra == "all"
40
- Requires-Dist: motor>=3.3.0; extra == "all"
41
- Requires-Dist: SQLAlchemy[asyncio]>=2.0.0; extra == "all"
38
+ Requires-Dist: beanie<3,>=2.0; extra == "all"
39
+ Requires-Dist: SQLAlchemy[asyncio]<3,>=2.0.30; extra == "all"
42
40
  Requires-Dist: psycopg2>=2.9.0; extra == "all"
43
41
  Requires-Dist: sqlmodel>=0.0.37; extra == "all"
44
42
  Requires-Dist: cookiecutter>=2.5.0; extra == "all"
@@ -48,18 +46,24 @@ Requires-Dist: mkdocstrings[python]>=0.27.0; extra == "all"
48
46
 
49
47
  <div align="center">
50
48
 
51
- # FastAPI BaseKit
49
+ <img src="docs/assets/logo-mark.svg" width="120" alt="fastapi-basekit">
52
50
 
53
- **Toolkit base para construir APIs FastAPI rápido — sin reinventar repos, services y controllers.**
51
+ # fastapi-basekit
54
52
 
55
- [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=teal)](https://pypi.org/project/fastapi-basekit/)
56
- ![Python](https://img.shields.io/badge/python-3.11+-blue?style=flat-square&logo=python)
57
- ![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi)
58
- ![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-red?style=flat-square)
59
- ![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb)
60
- ![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)
53
+ **FastAPI toolkit con repos, services y controllers listos para producción.**
54
+ **Multi-ORM · CLI scaffolder · plugin Claude Code.**
61
55
 
62
- [**Docs**](https://mundobien2025.github.io/fastapi-basekit) · [**PyPI**](https://pypi.org/project/fastapi-basekit/) · [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) · [**Changelog**](./CHANGELOG.md)
56
+ [![PyPI](https://img.shields.io/pypi/v/fastapi-basekit?style=flat-square&color=009485&logo=pypi&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
57
+ [![Python](https://img.shields.io/badge/python-3.11+-2c5282?style=flat-square&logo=python&logoColor=white)](https://pypi.org/project/fastapi-basekit/)
58
+ [![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat-square&logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
59
+ [![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-2.0-c41616?style=flat-square)](https://www.sqlalchemy.org/)
60
+ [![Beanie](https://img.shields.io/badge/MongoDB-Beanie-47A248?style=flat-square&logo=mongodb&logoColor=white)](https://beanie-odm.dev/)
61
+ [![License](https://img.shields.io/badge/license-MIT-009485?style=flat-square)](./LICENSE)
62
+
63
+ [**Docs**](https://mundobien2025.github.io/fastapi-basekit) ·
64
+ [**PyPI**](https://pypi.org/project/fastapi-basekit/) ·
65
+ [**Issues**](https://github.com/mundobien2025/fastapi-basekit/issues) ·
66
+ [**Changelog**](./CHANGELOG.md)
63
67
 
64
68
  </div>
65
69
 
@@ -89,7 +93,7 @@ Abre http://localhost:8000/docs. Login con `admin@example.com` / `ChangeMe2026!`
89
93
 
90
94
  ## Documentación
91
95
 
92
- 📚 **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
96
+ **[mundobien2025.github.io/fastapi-basekit](https://mundobien2025.github.io/fastapi-basekit)**
93
97
 
94
98
  | Sección | Contenido |
95
99
  |---|---|
@@ -21,6 +21,7 @@ fastapi_basekit/aio/controller/base.py
21
21
  fastapi_basekit/aio/permissions/__init__.py
22
22
  fastapi_basekit/aio/permissions/base.py
23
23
  fastapi_basekit/aio/sqlalchemy/__init__.py
24
+ fastapi_basekit/aio/sqlalchemy/session.py
24
25
  fastapi_basekit/aio/sqlalchemy/controller/__init__.py
25
26
  fastapi_basekit/aio/sqlalchemy/controller/base.py
26
27
  fastapi_basekit/aio/sqlalchemy/repository/__init__.py
@@ -1,12 +1,11 @@
1
1
  fastapi>=0.116.1
2
- pydantic<3,>=2.11.7
2
+ pydantic<3,>=2.13.0
3
3
  fastapi-restful[all]>=0.6.0
4
- pyjwt>=2.10.1
4
+ pyjwt>=2.12.1
5
5
 
6
6
  [all]
7
- beanie>=1.24.0
8
- motor>=3.3.0
9
- SQLAlchemy[asyncio]>=2.0.0
7
+ beanie<3,>=2.0
8
+ SQLAlchemy[asyncio]<3,>=2.0.30
10
9
  psycopg2>=2.9.0
11
10
  sqlmodel>=0.0.37
12
11
  cookiecutter>=2.5.0
@@ -15,8 +14,7 @@ mkdocs-material>=9.5.0
15
14
  mkdocstrings[python]>=0.27.0
16
15
 
17
16
  [beanie]
18
- beanie>=1.24.0
19
- motor>=3.3.0
17
+ beanie<3,>=2.0
20
18
 
21
19
  [docs]
22
20
  mkdocs>=1.6.0
@@ -29,7 +27,7 @@ mike>=2.1.0
29
27
  cookiecutter>=2.5.0
30
28
 
31
29
  [sqlalchemy]
32
- SQLAlchemy[asyncio]>=2.0.0
30
+ SQLAlchemy[asyncio]<3,>=2.0.30
33
31
  psycopg2>=2.9.0
34
32
 
35
33
  [sqlmodel]
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fastapi-basekit"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Utilities and base classes for FastAPI async projects (Beanie, SQLAlchemy or SQLModel)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -25,9 +25,9 @@ classifiers = [
25
25
 
26
26
  dependencies = [
27
27
  "fastapi>=0.116.1",
28
- "pydantic>=2.11.7,<3",
28
+ "pydantic>=2.13.0,<3",
29
29
  "fastapi-restful[all]>=0.6.0",
30
- "pyjwt>=2.10.1",
30
+ "pyjwt>=2.12.1",
31
31
  ]
32
32
 
33
33
  [tool.setuptools]
@@ -46,11 +46,10 @@ basekit = "fastapi_basekit.cli:main"
46
46
 
47
47
  [project.optional-dependencies]
48
48
  beanie = [
49
- "beanie>=1.24.0",
50
- "motor>=3.3.0",
49
+ "beanie>=2.0,<3",
51
50
  ]
52
51
  sqlalchemy = [
53
- "SQLAlchemy[asyncio]>=2.0.0",
52
+ "SQLAlchemy[asyncio]>=2.0.30,<3",
54
53
  "psycopg2>=2.9.0",
55
54
  ]
56
55
  sqlmodel = [
@@ -67,9 +66,8 @@ docs = [
67
66
  "mike>=2.1.0",
68
67
  ]
69
68
  all = [
70
- "beanie>=1.24.0",
71
- "motor>=3.3.0",
72
- "SQLAlchemy[asyncio]>=2.0.0",
69
+ "beanie>=2.0,<3",
70
+ "SQLAlchemy[asyncio]>=2.0.30,<3",
73
71
  "psycopg2>=2.9.0",
74
72
  "sqlmodel>=0.0.37",
75
73
  "cookiecutter>=2.5.0",
File without changes