fastapi-fullstack 0.1.7__py3-none-any.whl

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 (241) hide show
  1. fastapi_fullstack-0.1.7.dist-info/METADATA +739 -0
  2. fastapi_fullstack-0.1.7.dist-info/RECORD +241 -0
  3. fastapi_fullstack-0.1.7.dist-info/WHEEL +4 -0
  4. fastapi_fullstack-0.1.7.dist-info/entry_points.txt +2 -0
  5. fastapi_fullstack-0.1.7.dist-info/licenses/LICENSE +21 -0
  6. fastapi_gen/__init__.py +3 -0
  7. fastapi_gen/cli.py +442 -0
  8. fastapi_gen/config.py +356 -0
  9. fastapi_gen/generator.py +207 -0
  10. fastapi_gen/prompts.py +874 -0
  11. fastapi_gen/template/VARIABLES.md +276 -0
  12. fastapi_gen/template/cookiecutter.json +93 -0
  13. fastapi_gen/template/hooks/post_gen_project.py +355 -0
  14. fastapi_gen/template/{{cookiecutter.project_slug}}/.env.prod.example +56 -0
  15. fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
  16. fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +109 -0
  17. fastapi_gen/template/{{cookiecutter.project_slug}}/AGENTS.md +55 -0
  18. fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +99 -0
  19. fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +315 -0
  20. fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +768 -0
  21. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
  22. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.env.example +155 -0
  23. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
  24. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
  25. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
  26. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
  27. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
  28. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
  29. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
  30. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +447 -0
  31. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +23 -0
  32. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +226 -0
  33. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +226 -0
  34. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +10 -0
  35. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
  36. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
  37. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
  38. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +541 -0
  39. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +98 -0
  40. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
  41. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
  42. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
  43. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +902 -0
  44. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
  45. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +498 -0
  46. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
  47. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
  48. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
  49. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
  50. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
  51. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
  52. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
  53. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
  54. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
  55. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
  56. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
  57. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
  58. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
  59. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
  60. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
  61. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
  62. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +267 -0
  63. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
  64. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
  65. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
  66. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
  67. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
  68. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
  69. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
  70. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
  71. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
  72. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
  73. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
  74. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
  75. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
  76. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
  77. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
  78. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
  79. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +130 -0
  80. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +334 -0
  81. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
  82. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
  83. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
  84. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
  85. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +838 -0
  86. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
  87. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
  88. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
  89. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
  90. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
  91. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
  92. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +192 -0
  93. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
  94. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
  95. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
  96. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
  97. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
  98. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
  99. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +850 -0
  100. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
  101. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
  102. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
  103. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
  104. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
  105. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
  106. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
  107. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
  108. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
  109. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
  110. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
  111. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
  112. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
  113. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +180 -0
  114. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
  115. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
  116. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
  117. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
  118. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
  119. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
  120. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
  121. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
  122. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
  123. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +890 -0
  124. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +261 -0
  125. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
  126. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
  127. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
  128. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
  129. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
  130. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
  131. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
  132. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
  133. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
  134. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
  135. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +435 -0
  136. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
  137. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/adding_features.md +132 -0
  138. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/architecture.md +63 -0
  139. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/patterns.md +161 -0
  140. fastapi_gen/template/{{cookiecutter.project_slug}}/docs/testing.md +120 -0
  141. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +40 -0
  142. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
  143. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
  144. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
  145. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
  146. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
  147. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +648 -0
  148. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
  149. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
  150. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
  151. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
  152. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
  153. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
  154. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
  155. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
  156. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +69 -0
  157. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
  158. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
  159. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +11 -0
  160. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +5 -0
  161. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +5 -0
  162. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +48 -0
  163. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +99 -0
  164. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +17 -0
  165. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +152 -0
  166. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +113 -0
  167. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +46 -0
  168. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +73 -0
  169. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
  170. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
  171. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
  172. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
  173. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
  174. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
  175. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
  176. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
  177. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
  178. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
  179. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +323 -0
  180. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +22 -0
  181. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
  182. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
  183. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
  184. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
  185. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +234 -0
  186. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +72 -0
  187. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +328 -0
  188. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +46 -0
  189. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +11 -0
  190. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +295 -0
  191. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +167 -0
  192. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +79 -0
  193. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
  194. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +79 -0
  195. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
  196. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
  197. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
  198. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +65 -0
  199. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
  200. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +82 -0
  201. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
  202. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
  203. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +105 -0
  204. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
  205. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
  206. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +56 -0
  207. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
  208. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +13 -0
  209. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
  210. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
  211. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +109 -0
  212. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +7 -0
  213. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
  214. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
  215. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +181 -0
  216. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +165 -0
  217. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
  218. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +37 -0
  219. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
  220. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
  221. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
  222. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
  223. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
  224. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +31 -0
  225. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
  226. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +64 -0
  227. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +17 -0
  228. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
  229. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
  230. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +9 -0
  231. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +255 -0
  232. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +17 -0
  233. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
  234. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
  235. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
  236. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +83 -0
  237. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
  238. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
  239. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
  240. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
  241. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
@@ -0,0 +1,222 @@
1
+ {%- if cookiecutter.include_example_crud and cookiecutter.use_postgresql %}
2
+ """Item repository (PostgreSQL async).
3
+
4
+ Contains database operations for Item entity. Business logic
5
+ should be handled by ItemService in app/services/item.py.
6
+ """
7
+
8
+ from uuid import UUID
9
+
10
+ from sqlalchemy import select
11
+ from sqlalchemy.ext.asyncio import AsyncSession
12
+
13
+ from app.db.models.item import Item
14
+
15
+
16
+ async def get_by_id(db: AsyncSession, item_id: UUID) -> Item | None:
17
+ """Get item by ID."""
18
+ return await db.get(Item, item_id)
19
+
20
+
21
+ async def get_multi(
22
+ db: AsyncSession,
23
+ *,
24
+ skip: int = 0,
25
+ limit: int = 100,
26
+ active_only: bool = False,
27
+ ) -> list[Item]:
28
+ """Get multiple items with pagination."""
29
+ query = select(Item)
30
+ if active_only:
31
+ query = query.where(Item.is_active == True) # noqa: E712
32
+ query = query.offset(skip).limit(limit)
33
+ result = await db.execute(query)
34
+ return list(result.scalars().all())
35
+
36
+
37
+ async def create(
38
+ db: AsyncSession,
39
+ *,
40
+ title: str,
41
+ description: str | None = None,
42
+ ) -> Item:
43
+ """Create a new item."""
44
+ item = Item(
45
+ title=title,
46
+ description=description,
47
+ )
48
+ db.add(item)
49
+ await db.flush()
50
+ await db.refresh(item)
51
+ return item
52
+
53
+
54
+ async def update(
55
+ db: AsyncSession,
56
+ *,
57
+ db_item: Item,
58
+ update_data: dict,
59
+ ) -> Item:
60
+ """Update an item."""
61
+ for field, value in update_data.items():
62
+ setattr(db_item, field, value)
63
+
64
+ db.add(db_item)
65
+ await db.flush()
66
+ await db.refresh(db_item)
67
+ return db_item
68
+
69
+
70
+ async def delete(db: AsyncSession, item_id: UUID) -> Item | None:
71
+ """Delete an item."""
72
+ item = await get_by_id(db, item_id)
73
+ if item:
74
+ await db.delete(item)
75
+ await db.flush()
76
+ return item
77
+
78
+
79
+ {%- elif cookiecutter.include_example_crud and cookiecutter.use_sqlite %}
80
+ """Item repository (SQLite sync).
81
+
82
+ Contains database operations for Item entity. Business logic
83
+ should be handled by ItemService in app/services/item.py.
84
+ """
85
+
86
+ from sqlalchemy import select
87
+ from sqlalchemy.orm import Session
88
+
89
+ from app.db.models.item import Item
90
+
91
+
92
+ def get_by_id(db: Session, item_id: str) -> Item | None:
93
+ """Get item by ID."""
94
+ return db.get(Item, item_id)
95
+
96
+
97
+ def get_multi(
98
+ db: Session,
99
+ *,
100
+ skip: int = 0,
101
+ limit: int = 100,
102
+ active_only: bool = False,
103
+ ) -> list[Item]:
104
+ """Get multiple items with pagination."""
105
+ query = select(Item)
106
+ if active_only:
107
+ query = query.where(Item.is_active == True) # noqa: E712
108
+ query = query.offset(skip).limit(limit)
109
+ result = db.execute(query)
110
+ return list(result.scalars().all())
111
+
112
+
113
+ def create(
114
+ db: Session,
115
+ *,
116
+ title: str,
117
+ description: str | None = None,
118
+ ) -> Item:
119
+ """Create a new item."""
120
+ item = Item(
121
+ title=title,
122
+ description=description,
123
+ )
124
+ db.add(item)
125
+ db.flush()
126
+ db.refresh(item)
127
+ return item
128
+
129
+
130
+ def update(
131
+ db: Session,
132
+ *,
133
+ db_item: Item,
134
+ update_data: dict,
135
+ ) -> Item:
136
+ """Update an item."""
137
+ for field, value in update_data.items():
138
+ setattr(db_item, field, value)
139
+
140
+ db.add(db_item)
141
+ db.flush()
142
+ db.refresh(db_item)
143
+ return db_item
144
+
145
+
146
+ def delete(db: Session, item_id: str) -> Item | None:
147
+ """Delete an item."""
148
+ item = get_by_id(db, item_id)
149
+ if item:
150
+ db.delete(item)
151
+ db.flush()
152
+ return item
153
+
154
+
155
+ {%- elif cookiecutter.include_example_crud and cookiecutter.use_mongodb %}
156
+ """Item repository (MongoDB).
157
+
158
+ Contains database operations for Item entity. Business logic
159
+ should be handled by ItemService in app/services/item.py.
160
+ """
161
+
162
+ from datetime import UTC, datetime
163
+
164
+ from app.db.models.item import Item
165
+
166
+
167
+ async def get_by_id(item_id: str) -> Item | None:
168
+ """Get item by ID."""
169
+ return await Item.get(item_id)
170
+
171
+
172
+ async def get_multi(
173
+ *,
174
+ skip: int = 0,
175
+ limit: int = 100,
176
+ active_only: bool = False,
177
+ ) -> list[Item]:
178
+ """Get multiple items with pagination."""
179
+ query = Item.find_all()
180
+ if active_only:
181
+ query = Item.find(Item.is_active == True) # noqa: E712
182
+ return await query.skip(skip).limit(limit).to_list()
183
+
184
+
185
+ async def create(
186
+ *,
187
+ title: str,
188
+ description: str | None = None,
189
+ ) -> Item:
190
+ """Create a new item."""
191
+ item = Item(
192
+ title=title,
193
+ description=description,
194
+ )
195
+ await item.insert()
196
+ return item
197
+
198
+
199
+ async def update(
200
+ *,
201
+ db_item: Item,
202
+ update_data: dict,
203
+ ) -> Item:
204
+ """Update an item."""
205
+ for field, value in update_data.items():
206
+ setattr(db_item, field, value)
207
+ db_item.updated_at = datetime.now(UTC)
208
+ await db_item.save()
209
+ return db_item
210
+
211
+
212
+ async def delete(item_id: str) -> Item | None:
213
+ """Delete an item."""
214
+ item = await get_by_id(item_id)
215
+ if item:
216
+ await item.delete()
217
+ return item
218
+
219
+
220
+ {%- else %}
221
+ """Item repository - not configured."""
222
+ {%- endif %}
@@ -0,0 +1,318 @@
1
+ {%- if cookiecutter.enable_session_management and cookiecutter.use_jwt %}
2
+ {%- if cookiecutter.use_postgresql %}
3
+ """Session repository (PostgreSQL async)."""
4
+
5
+ from datetime import datetime
6
+ from uuid import UUID
7
+
8
+ from sqlalchemy import select, update
9
+ from sqlalchemy.ext.asyncio import AsyncSession
10
+
11
+ from app.db.models.session import Session
12
+
13
+
14
+ async def get_by_id(db: AsyncSession, session_id: UUID) -> Session | None:
15
+ """Get session by ID."""
16
+ return await db.get(Session, session_id)
17
+
18
+
19
+ async def get_by_refresh_token_hash(db: AsyncSession, token_hash: str) -> Session | None:
20
+ """Get session by refresh token hash."""
21
+ result = await db.execute(
22
+ select(Session).where(
23
+ Session.refresh_token_hash == token_hash,
24
+ Session.is_active.is_(True),
25
+ )
26
+ )
27
+ return result.scalar_one_or_none()
28
+
29
+
30
+ async def get_user_sessions(
31
+ db: AsyncSession,
32
+ user_id: UUID,
33
+ *,
34
+ active_only: bool = True,
35
+ ) -> list[Session]:
36
+ """Get all sessions for a user."""
37
+ query = select(Session).where(Session.user_id == user_id)
38
+ if active_only:
39
+ query = query.where(Session.is_active.is_(True))
40
+ query = query.order_by(Session.last_used_at.desc())
41
+ result = await db.execute(query)
42
+ return list(result.scalars().all())
43
+
44
+
45
+ async def create(
46
+ db: AsyncSession,
47
+ *,
48
+ user_id: UUID,
49
+ refresh_token_hash: str,
50
+ expires_at: datetime,
51
+ device_name: str | None = None,
52
+ device_type: str | None = None,
53
+ ip_address: str | None = None,
54
+ user_agent: str | None = None,
55
+ ) -> Session:
56
+ """Create a new session."""
57
+ session = Session(
58
+ user_id=user_id,
59
+ refresh_token_hash=refresh_token_hash,
60
+ expires_at=expires_at,
61
+ device_name=device_name,
62
+ device_type=device_type,
63
+ ip_address=ip_address,
64
+ user_agent=user_agent,
65
+ )
66
+ db.add(session)
67
+ await db.flush()
68
+ await db.refresh(session)
69
+ return session
70
+
71
+
72
+ async def update_last_used(db: AsyncSession, session_id: UUID) -> None:
73
+ """Update session last used timestamp."""
74
+ await db.execute(
75
+ update(Session)
76
+ .where(Session.id == session_id)
77
+ .values(last_used_at=datetime.utcnow())
78
+ )
79
+ await db.flush()
80
+
81
+
82
+ async def deactivate(db: AsyncSession, session_id: UUID) -> Session | None:
83
+ """Deactivate a session (logout)."""
84
+ session = await get_by_id(db, session_id)
85
+ if session:
86
+ session.is_active = False
87
+ db.add(session)
88
+ await db.flush()
89
+ return session
90
+
91
+
92
+ async def deactivate_all_user_sessions(db: AsyncSession, user_id: UUID) -> int:
93
+ """Deactivate all sessions for a user. Returns count of deactivated sessions."""
94
+ result = await db.execute(
95
+ update(Session)
96
+ .where(Session.user_id == user_id, Session.is_active.is_(True))
97
+ .values(is_active=False)
98
+ )
99
+ await db.flush()
100
+ return result.rowcount
101
+
102
+
103
+ async def deactivate_by_refresh_token_hash(db: AsyncSession, token_hash: str) -> Session | None:
104
+ """Deactivate session by refresh token hash."""
105
+ session = await get_by_refresh_token_hash(db, token_hash)
106
+ if session:
107
+ session.is_active = False
108
+ db.add(session)
109
+ await db.flush()
110
+ return session
111
+
112
+
113
+ {%- elif cookiecutter.use_sqlite %}
114
+ """Session repository (SQLite sync)."""
115
+
116
+ from datetime import datetime
117
+
118
+ from sqlalchemy import select, update
119
+ from sqlalchemy.orm import Session as DBSession
120
+
121
+ from app.db.models.session import Session
122
+
123
+
124
+ def get_by_id(db: DBSession, session_id: str) -> Session | None:
125
+ """Get session by ID."""
126
+ return db.get(Session, session_id)
127
+
128
+
129
+ def get_by_refresh_token_hash(db: DBSession, token_hash: str) -> Session | None:
130
+ """Get session by refresh token hash."""
131
+ result = db.execute(
132
+ select(Session).where(
133
+ Session.refresh_token_hash == token_hash,
134
+ Session.is_active.is_(True),
135
+ )
136
+ )
137
+ return result.scalar_one_or_none()
138
+
139
+
140
+ def get_user_sessions(
141
+ db: DBSession,
142
+ user_id: str,
143
+ *,
144
+ active_only: bool = True,
145
+ ) -> list[Session]:
146
+ """Get all sessions for a user."""
147
+ query = select(Session).where(Session.user_id == user_id)
148
+ if active_only:
149
+ query = query.where(Session.is_active.is_(True))
150
+ query = query.order_by(Session.last_used_at.desc())
151
+ result = db.execute(query)
152
+ return list(result.scalars().all())
153
+
154
+
155
+ def create(
156
+ db: DBSession,
157
+ *,
158
+ user_id: str,
159
+ refresh_token_hash: str,
160
+ expires_at: datetime,
161
+ device_name: str | None = None,
162
+ device_type: str | None = None,
163
+ ip_address: str | None = None,
164
+ user_agent: str | None = None,
165
+ ) -> Session:
166
+ """Create a new session."""
167
+ session = Session(
168
+ user_id=user_id,
169
+ refresh_token_hash=refresh_token_hash,
170
+ expires_at=expires_at,
171
+ device_name=device_name,
172
+ device_type=device_type,
173
+ ip_address=ip_address,
174
+ user_agent=user_agent,
175
+ )
176
+ db.add(session)
177
+ db.flush()
178
+ db.refresh(session)
179
+ return session
180
+
181
+
182
+ def update_last_used(db: DBSession, session_id: str) -> None:
183
+ """Update session last used timestamp."""
184
+ db.execute(
185
+ update(Session)
186
+ .where(Session.id == session_id)
187
+ .values(last_used_at=datetime.utcnow())
188
+ )
189
+ db.flush()
190
+
191
+
192
+ def deactivate(db: DBSession, session_id: str) -> Session | None:
193
+ """Deactivate a session (logout)."""
194
+ session = get_by_id(db, session_id)
195
+ if session:
196
+ session.is_active = False
197
+ db.add(session)
198
+ db.flush()
199
+ return session
200
+
201
+
202
+ def deactivate_all_user_sessions(db: DBSession, user_id: str) -> int:
203
+ """Deactivate all sessions for a user. Returns count of deactivated sessions."""
204
+ result = db.execute(
205
+ update(Session)
206
+ .where(Session.user_id == user_id, Session.is_active.is_(True))
207
+ .values(is_active=False)
208
+ )
209
+ db.flush()
210
+ return result.rowcount
211
+
212
+
213
+ def deactivate_by_refresh_token_hash(db: DBSession, token_hash: str) -> Session | None:
214
+ """Deactivate session by refresh token hash."""
215
+ session = get_by_refresh_token_hash(db, token_hash)
216
+ if session:
217
+ session.is_active = False
218
+ db.add(session)
219
+ db.flush()
220
+ return session
221
+
222
+
223
+ {%- elif cookiecutter.use_mongodb %}
224
+ """Session repository (MongoDB)."""
225
+
226
+ from datetime import UTC, datetime
227
+
228
+ from app.db.models.session import Session
229
+
230
+
231
+ async def get_by_id(session_id: str) -> Session | None:
232
+ """Get session by ID."""
233
+ return await Session.get(session_id)
234
+
235
+
236
+ async def get_by_refresh_token_hash(token_hash: str) -> Session | None:
237
+ """Get session by refresh token hash."""
238
+ return await Session.find_one(
239
+ Session.refresh_token_hash == token_hash,
240
+ Session.is_active == True,
241
+ )
242
+
243
+
244
+ async def get_user_sessions(
245
+ user_id: str,
246
+ *,
247
+ active_only: bool = True,
248
+ ) -> list[Session]:
249
+ """Get all sessions for a user."""
250
+ query = Session.find(Session.user_id == user_id)
251
+ if active_only:
252
+ query = query.find(Session.is_active == True)
253
+ return await query.sort(-Session.last_used_at).to_list()
254
+
255
+
256
+ async def create(
257
+ *,
258
+ user_id: str,
259
+ refresh_token_hash: str,
260
+ expires_at: datetime,
261
+ device_name: str | None = None,
262
+ device_type: str | None = None,
263
+ ip_address: str | None = None,
264
+ user_agent: str | None = None,
265
+ ) -> Session:
266
+ """Create a new session."""
267
+ session = Session(
268
+ user_id=user_id,
269
+ refresh_token_hash=refresh_token_hash,
270
+ expires_at=expires_at,
271
+ device_name=device_name,
272
+ device_type=device_type,
273
+ ip_address=ip_address,
274
+ user_agent=user_agent,
275
+ )
276
+ await session.insert()
277
+ return session
278
+
279
+
280
+ async def update_last_used(session_id: str) -> None:
281
+ """Update session last used timestamp."""
282
+ session = await get_by_id(session_id)
283
+ if session:
284
+ session.last_used_at = datetime.now(UTC)
285
+ await session.save()
286
+
287
+
288
+ async def deactivate(session_id: str) -> Session | None:
289
+ """Deactivate a session (logout)."""
290
+ session = await get_by_id(session_id)
291
+ if session:
292
+ session.is_active = False
293
+ await session.save()
294
+ return session
295
+
296
+
297
+ async def deactivate_all_user_sessions(user_id: str) -> int:
298
+ """Deactivate all sessions for a user. Returns count of deactivated sessions."""
299
+ result = await Session.find(
300
+ Session.user_id == user_id,
301
+ Session.is_active == True,
302
+ ).update({"$set": {"is_active": False}})
303
+ return result.modified_count if result else 0
304
+
305
+
306
+ async def deactivate_by_refresh_token_hash(token_hash: str) -> Session | None:
307
+ """Deactivate session by refresh token hash."""
308
+ session = await get_by_refresh_token_hash(token_hash)
309
+ if session:
310
+ session.is_active = False
311
+ await session.save()
312
+ return session
313
+
314
+
315
+ {%- endif %}
316
+ {%- else %}
317
+ """Session repository - not configured."""
318
+ {%- endif %}