fastapi-fullstack 0.1.2__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 (221) hide show
  1. fastapi_fullstack-0.1.2.dist-info/METADATA +545 -0
  2. fastapi_fullstack-0.1.2.dist-info/RECORD +221 -0
  3. fastapi_fullstack-0.1.2.dist-info/WHEEL +4 -0
  4. fastapi_fullstack-0.1.2.dist-info/entry_points.txt +2 -0
  5. fastapi_fullstack-0.1.2.dist-info/licenses/LICENSE +21 -0
  6. fastapi_gen/__init__.py +3 -0
  7. fastapi_gen/cli.py +256 -0
  8. fastapi_gen/config.py +255 -0
  9. fastapi_gen/generator.py +181 -0
  10. fastapi_gen/prompts.py +648 -0
  11. fastapi_gen/template/cookiecutter.json +76 -0
  12. fastapi_gen/template/hooks/post_gen_project.py +111 -0
  13. fastapi_gen/template/{{cookiecutter.project_slug}}/.env.example +136 -0
  14. fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
  15. fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +108 -0
  16. fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +357 -0
  17. fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +298 -0
  18. fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +723 -0
  19. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
  20. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
  21. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
  22. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
  23. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
  24. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
  25. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
  26. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
  27. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +115 -0
  28. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +13 -0
  29. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +202 -0
  30. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
  31. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
  32. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
  33. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +528 -0
  34. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +85 -0
  35. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
  36. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
  37. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
  38. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +448 -0
  39. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
  40. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +490 -0
  41. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
  42. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
  43. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
  44. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
  45. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
  46. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
  47. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
  48. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
  49. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
  50. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
  51. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
  52. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
  53. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
  54. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
  55. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
  56. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
  57. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +247 -0
  58. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
  59. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
  60. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
  61. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
  62. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
  63. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
  64. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
  65. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
  66. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
  67. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
  68. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
  69. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
  70. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
  71. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
  72. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
  73. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
  74. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +113 -0
  75. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +326 -0
  76. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
  77. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
  78. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
  79. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
  80. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +760 -0
  81. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
  82. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
  83. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
  84. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
  85. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
  86. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
  87. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +195 -0
  88. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
  89. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
  90. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
  91. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
  92. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
  93. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
  94. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +797 -0
  95. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
  96. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
  97. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
  98. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
  99. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
  100. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
  101. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
  102. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
  103. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
  104. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
  105. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
  106. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
  107. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
  108. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +158 -0
  109. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
  110. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
  111. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
  112. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
  113. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
  114. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
  115. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
  116. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
  117. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
  118. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +121 -0
  119. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
  120. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
  121. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
  122. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
  123. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
  124. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
  125. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
  126. fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
  127. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
  128. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
  129. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +382 -0
  130. fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
  131. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
  132. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
  133. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
  134. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
  135. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
  136. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +693 -0
  137. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
  138. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
  139. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
  140. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
  141. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
  142. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
  143. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
  144. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
  145. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +66 -0
  146. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
  147. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
  148. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/layout.tsx +11 -0
  149. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/login/page.tsx +5 -0
  150. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(auth)/register/page.tsx +5 -0
  151. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/chat/page.tsx +20 -0
  152. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/dashboard/page.tsx +99 -0
  153. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/layout.tsx +17 -0
  154. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/(dashboard)/profile/page.tsx +156 -0
  155. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
  156. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
  157. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
  158. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
  159. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
  160. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
  161. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
  162. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
  163. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
  164. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
  165. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/auth/callback/page.tsx +96 -0
  166. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +108 -0
  167. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +25 -0
  168. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/page.tsx +73 -0
  169. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
  170. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
  171. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
  172. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
  173. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +135 -0
  174. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +73 -0
  175. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +261 -0
  176. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +8 -0
  177. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +63 -0
  178. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
  179. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +60 -0
  180. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
  181. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
  182. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
  183. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +45 -0
  184. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
  185. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +48 -0
  186. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
  187. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
  188. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +83 -0
  189. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
  190. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
  191. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +54 -0
  192. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
  193. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +12 -0
  194. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
  195. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
  196. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +6 -0
  197. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
  198. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
  199. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +175 -0
  200. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
  201. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +32 -0
  202. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
  203. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
  204. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
  205. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
  206. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
  207. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +33 -0
  208. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
  209. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +48 -0
  210. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
  211. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
  212. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +6 -0
  213. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
  214. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
  215. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
  216. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +81 -0
  217. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
  218. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
  219. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
  220. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
  221. fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
fastapi_gen/prompts.py ADDED
@@ -0,0 +1,648 @@
1
+ """Interactive prompts for project configuration."""
2
+
3
+ from typing import Any, cast
4
+
5
+ import questionary
6
+ from rich.console import Console
7
+ from rich.panel import Panel
8
+ from rich.text import Text
9
+
10
+ from .config import (
11
+ AdminEnvironmentType,
12
+ AuthType,
13
+ BackgroundTaskType,
14
+ CIType,
15
+ DatabaseType,
16
+ FrontendType,
17
+ LogfireFeatures,
18
+ OAuthProvider,
19
+ ProjectConfig,
20
+ WebSocketAuthType,
21
+ )
22
+
23
+ console = Console()
24
+
25
+
26
+ def show_header() -> None:
27
+ """Display the generator header."""
28
+ header = Text()
29
+ header.append("FastAPI Project Generator", style="bold cyan")
30
+ header.append("\n")
31
+ header.append("with Logfire Observability", style="dim")
32
+ console.print(Panel(header, title="[bold green]fastapi-gen[/]", border_style="green"))
33
+ console.print()
34
+
35
+
36
+ def _check_cancelled(value: Any) -> Any:
37
+ """Check if the user cancelled the prompt and raise KeyboardInterrupt if so."""
38
+ if value is None:
39
+ raise KeyboardInterrupt
40
+ return value
41
+
42
+
43
+ def prompt_basic_info() -> dict[str, str]:
44
+ """Prompt for basic project information."""
45
+ console.print("[bold cyan]Basic Information[/]")
46
+ console.print()
47
+
48
+ project_name = _check_cancelled(
49
+ questionary.text(
50
+ "Project name:",
51
+ validate=lambda x: len(x) > 0 and x[0].isalpha() and x.replace("_", "").isalnum(),
52
+ ).ask()
53
+ )
54
+
55
+ project_description = _check_cancelled(
56
+ questionary.text(
57
+ "Project description:",
58
+ default="My FastAPI project",
59
+ ).ask()
60
+ )
61
+
62
+ author_name = _check_cancelled(
63
+ questionary.text(
64
+ "Author name:",
65
+ default="Your Name",
66
+ ).ask()
67
+ )
68
+
69
+ author_email = _check_cancelled(
70
+ questionary.text(
71
+ "Author email:",
72
+ default="your@email.com",
73
+ ).ask()
74
+ )
75
+
76
+ return {
77
+ "project_name": project_name,
78
+ "project_description": project_description,
79
+ "author_name": author_name,
80
+ "author_email": author_email,
81
+ }
82
+
83
+
84
+ def prompt_database() -> DatabaseType:
85
+ """Prompt for database selection."""
86
+ console.print()
87
+ console.print("[bold cyan]Database Configuration[/]")
88
+ console.print()
89
+
90
+ choices = [
91
+ questionary.Choice("PostgreSQL (async - asyncpg)", value=DatabaseType.POSTGRESQL),
92
+ questionary.Choice("MongoDB (async - motor)", value=DatabaseType.MONGODB),
93
+ questionary.Choice("SQLite (sync)", value=DatabaseType.SQLITE),
94
+ questionary.Choice("None", value=DatabaseType.NONE),
95
+ ]
96
+
97
+ return cast(
98
+ DatabaseType,
99
+ _check_cancelled(
100
+ questionary.select(
101
+ "Select database:",
102
+ choices=choices,
103
+ default=choices[0],
104
+ ).ask()
105
+ ),
106
+ )
107
+
108
+
109
+ def prompt_auth() -> AuthType:
110
+ """Prompt for authentication method."""
111
+ console.print()
112
+ console.print("[bold cyan]Authentication[/]")
113
+ console.print()
114
+
115
+ choices = [
116
+ questionary.Choice("JWT + User Management", value=AuthType.JWT),
117
+ questionary.Choice("API Key (header-based)", value=AuthType.API_KEY),
118
+ questionary.Choice("Both (JWT + API Key fallback)", value=AuthType.BOTH),
119
+ questionary.Choice("None", value=AuthType.NONE),
120
+ ]
121
+
122
+ return cast(
123
+ AuthType,
124
+ _check_cancelled(
125
+ questionary.select(
126
+ "Select auth method:",
127
+ choices=choices,
128
+ default=choices[0],
129
+ ).ask()
130
+ ),
131
+ )
132
+
133
+
134
+ def prompt_oauth() -> OAuthProvider:
135
+ """Prompt for OAuth provider selection."""
136
+ console.print()
137
+ console.print("[bold cyan]OAuth2 Social Login[/]")
138
+ console.print()
139
+
140
+ choices = [
141
+ questionary.Choice("None (email/password only)", value=OAuthProvider.NONE),
142
+ questionary.Choice("Google OAuth2", value=OAuthProvider.GOOGLE),
143
+ ]
144
+
145
+ return cast(
146
+ OAuthProvider,
147
+ _check_cancelled(
148
+ questionary.select(
149
+ "Enable social login?",
150
+ choices=choices,
151
+ default=choices[0],
152
+ ).ask()
153
+ ),
154
+ )
155
+
156
+
157
+ def prompt_logfire() -> tuple[bool, LogfireFeatures]:
158
+ """Prompt for Logfire configuration."""
159
+ console.print()
160
+ console.print("[bold cyan]Observability (Logfire)[/]")
161
+ console.print()
162
+
163
+ enable_logfire = _check_cancelled(
164
+ questionary.confirm(
165
+ "Enable Logfire integration?",
166
+ default=True,
167
+ ).ask()
168
+ )
169
+
170
+ if not enable_logfire:
171
+ return False, LogfireFeatures()
172
+
173
+ features = _check_cancelled(
174
+ questionary.checkbox(
175
+ "Logfire features:",
176
+ choices=[
177
+ questionary.Choice("FastAPI instrumentation", value="fastapi", checked=True),
178
+ questionary.Choice("Database instrumentation", value="database", checked=True),
179
+ questionary.Choice("Redis instrumentation", value="redis", checked=False),
180
+ questionary.Choice("Celery/Taskiq instrumentation", value="celery", checked=False),
181
+ questionary.Choice("HTTPX instrumentation", value="httpx", checked=False),
182
+ ],
183
+ ).ask()
184
+ )
185
+
186
+ return True, LogfireFeatures(
187
+ fastapi="fastapi" in features,
188
+ database="database" in features,
189
+ redis="redis" in features,
190
+ celery="celery" in features,
191
+ httpx="httpx" in features,
192
+ )
193
+
194
+
195
+ def prompt_background_tasks() -> BackgroundTaskType:
196
+ """Prompt for background task system."""
197
+ console.print()
198
+ console.print("[bold cyan]Background Tasks[/]")
199
+ console.print()
200
+
201
+ choices = [
202
+ questionary.Choice("None (use FastAPI BackgroundTasks)", value=BackgroundTaskType.NONE),
203
+ questionary.Choice("Celery (classic, battle-tested)", value=BackgroundTaskType.CELERY),
204
+ questionary.Choice("Taskiq (async-native, modern)", value=BackgroundTaskType.TASKIQ),
205
+ questionary.Choice("ARQ (lightweight async Redis)", value=BackgroundTaskType.ARQ),
206
+ ]
207
+
208
+ return cast(
209
+ BackgroundTaskType,
210
+ _check_cancelled(
211
+ questionary.select(
212
+ "Select background task system:",
213
+ choices=choices,
214
+ default=choices[0],
215
+ ).ask()
216
+ ),
217
+ )
218
+
219
+
220
+ def prompt_integrations() -> dict[str, bool]:
221
+ """Prompt for optional integrations."""
222
+ console.print()
223
+ console.print("[bold cyan]Optional Integrations[/]")
224
+ console.print()
225
+
226
+ features = _check_cancelled(
227
+ questionary.checkbox(
228
+ "Select additional features:",
229
+ choices=[
230
+ questionary.Choice("Redis (caching/sessions)", value="redis"),
231
+ questionary.Choice("Caching (fastapi-cache2)", value="caching"),
232
+ questionary.Choice("Rate limiting (slowapi)", value="rate_limiting"),
233
+ questionary.Choice(
234
+ "Pagination (fastapi-pagination)", value="pagination", checked=True
235
+ ),
236
+ questionary.Choice("Sentry (error tracking)", value="sentry"),
237
+ questionary.Choice("Prometheus (metrics)", value="prometheus"),
238
+ questionary.Choice("Admin Panel (SQLAdmin)", value="admin_panel"),
239
+ questionary.Choice("WebSockets", value="websockets"),
240
+ questionary.Choice("File Storage (S3/MinIO)", value="file_storage"),
241
+ questionary.Choice("AI Agent (PydanticAI)", value="ai_agent"),
242
+ questionary.Choice("Webhooks (outbound events)", value="webhooks"),
243
+ questionary.Choice("Example CRUD (Item model)", value="example_crud", checked=True),
244
+ questionary.Choice("CORS middleware", value="cors", checked=True),
245
+ questionary.Choice("orjson (faster JSON)", value="orjson", checked=True),
246
+ ],
247
+ ).ask()
248
+ )
249
+
250
+ return {
251
+ "enable_redis": "redis" in features,
252
+ "enable_caching": "caching" in features,
253
+ "enable_rate_limiting": "rate_limiting" in features,
254
+ "enable_pagination": "pagination" in features,
255
+ "enable_sentry": "sentry" in features,
256
+ "enable_prometheus": "prometheus" in features,
257
+ "enable_admin_panel": "admin_panel" in features,
258
+ "enable_websockets": "websockets" in features,
259
+ "enable_file_storage": "file_storage" in features,
260
+ "enable_ai_agent": "ai_agent" in features,
261
+ "enable_webhooks": "webhooks" in features,
262
+ "include_example_crud": "example_crud" in features,
263
+ "enable_cors": "cors" in features,
264
+ "enable_orjson": "orjson" in features,
265
+ }
266
+
267
+
268
+ def prompt_dev_tools() -> dict[str, Any]:
269
+ """Prompt for development tools."""
270
+ console.print()
271
+ console.print("[bold cyan]Development Tools[/]")
272
+ console.print()
273
+
274
+ features = _check_cancelled(
275
+ questionary.checkbox(
276
+ "Include dev tools:",
277
+ choices=[
278
+ questionary.Choice("pytest + fixtures", value="pytest", checked=True),
279
+ questionary.Choice("pre-commit hooks", value="precommit", checked=True),
280
+ questionary.Choice("Makefile", value="makefile", checked=True),
281
+ questionary.Choice("Docker + docker-compose", value="docker", checked=True),
282
+ questionary.Choice("Kubernetes manifests", value="kubernetes"),
283
+ ],
284
+ ).ask()
285
+ )
286
+
287
+ ci_type = _check_cancelled(
288
+ questionary.select(
289
+ "CI/CD system:",
290
+ choices=[
291
+ questionary.Choice("GitHub Actions", value=CIType.GITHUB),
292
+ questionary.Choice("GitLab CI", value=CIType.GITLAB),
293
+ questionary.Choice("None", value=CIType.NONE),
294
+ ],
295
+ ).ask()
296
+ )
297
+
298
+ return {
299
+ "enable_pytest": "pytest" in features,
300
+ "enable_precommit": "precommit" in features,
301
+ "enable_makefile": "makefile" in features,
302
+ "enable_docker": "docker" in features,
303
+ "enable_kubernetes": "kubernetes" in features,
304
+ "ci_type": ci_type,
305
+ }
306
+
307
+
308
+ def prompt_frontend() -> FrontendType:
309
+ """Prompt for frontend framework selection."""
310
+ console.print()
311
+ console.print("[bold cyan]Frontend Framework[/]")
312
+ console.print()
313
+
314
+ choices = [
315
+ questionary.Choice("None (API only)", value=FrontendType.NONE),
316
+ questionary.Choice("Next.js 15 (App Router, TypeScript, Bun)", value=FrontendType.NEXTJS),
317
+ ]
318
+
319
+ return cast(
320
+ FrontendType,
321
+ _check_cancelled(
322
+ questionary.select(
323
+ "Select frontend framework:",
324
+ choices=choices,
325
+ default=choices[0],
326
+ ).ask()
327
+ ),
328
+ )
329
+
330
+
331
+ def prompt_frontend_features() -> dict[str, bool]:
332
+ """Prompt for frontend-specific features."""
333
+ console.print()
334
+ console.print("[bold cyan]Frontend Features[/]")
335
+ console.print()
336
+
337
+ features = _check_cancelled(
338
+ questionary.checkbox(
339
+ "Select frontend features:",
340
+ choices=[
341
+ questionary.Choice("i18n (internationalization with next-intl)", value="i18n"),
342
+ ],
343
+ ).ask()
344
+ )
345
+
346
+ return {
347
+ "enable_i18n": "i18n" in features,
348
+ }
349
+
350
+
351
+ def prompt_websocket_auth() -> WebSocketAuthType:
352
+ """Prompt for WebSocket authentication method for AI Agent."""
353
+ console.print()
354
+ console.print("[bold cyan]AI Agent WebSocket Authentication[/]")
355
+ console.print()
356
+
357
+ choices = [
358
+ questionary.Choice("None (public access)", value=WebSocketAuthType.NONE),
359
+ questionary.Choice("JWT token required", value=WebSocketAuthType.JWT),
360
+ questionary.Choice("API Key required (query param)", value=WebSocketAuthType.API_KEY),
361
+ ]
362
+
363
+ return cast(
364
+ WebSocketAuthType,
365
+ _check_cancelled(
366
+ questionary.select(
367
+ "Select WebSocket authentication:",
368
+ choices=choices,
369
+ default=choices[0],
370
+ ).ask()
371
+ ),
372
+ )
373
+
374
+
375
+ def prompt_admin_config() -> tuple[AdminEnvironmentType, bool]:
376
+ """Prompt for admin panel configuration."""
377
+ console.print()
378
+ console.print("[bold cyan]Admin Panel Configuration[/]")
379
+ console.print()
380
+
381
+ env_choices = [
382
+ questionary.Choice(
383
+ "Development + Staging (recommended)", value=AdminEnvironmentType.DEV_STAGING
384
+ ),
385
+ questionary.Choice("Development only", value=AdminEnvironmentType.DEV_ONLY),
386
+ questionary.Choice("All environments", value=AdminEnvironmentType.ALL),
387
+ questionary.Choice("Disabled", value=AdminEnvironmentType.DISABLED),
388
+ ]
389
+
390
+ admin_environments = cast(
391
+ AdminEnvironmentType,
392
+ _check_cancelled(
393
+ questionary.select(
394
+ "Enable admin panel in which environments?",
395
+ choices=env_choices,
396
+ default=env_choices[0],
397
+ ).ask()
398
+ ),
399
+ )
400
+
401
+ # If disabled, skip auth question
402
+ if admin_environments == AdminEnvironmentType.DISABLED:
403
+ return admin_environments, False
404
+
405
+ require_auth = _check_cancelled(
406
+ questionary.confirm(
407
+ "Require authentication for admin panel? (superuser login)",
408
+ default=True,
409
+ ).ask()
410
+ )
411
+
412
+ return admin_environments, require_auth
413
+
414
+
415
+ def prompt_python_version() -> str:
416
+ """Prompt for Python version selection."""
417
+ console.print()
418
+ console.print("[bold cyan]Python Version[/]")
419
+ console.print()
420
+
421
+ choices = [
422
+ questionary.Choice("Python 3.12 (recommended)", value="3.12"),
423
+ questionary.Choice("Python 3.11", value="3.11"),
424
+ questionary.Choice("Python 3.13", value="3.13"),
425
+ ]
426
+
427
+ return cast(
428
+ str,
429
+ _check_cancelled(
430
+ questionary.select(
431
+ "Select Python version:",
432
+ choices=choices,
433
+ default=choices[0],
434
+ ).ask()
435
+ ),
436
+ )
437
+
438
+
439
+ def prompt_ports(has_frontend: bool) -> dict[str, int]:
440
+ """Prompt for port configuration."""
441
+ console.print()
442
+ console.print("[bold cyan]Port Configuration[/]")
443
+ console.print()
444
+
445
+ def validate_port(value: str) -> bool:
446
+ try:
447
+ port = int(value)
448
+ return 1024 <= port <= 65535
449
+ except ValueError:
450
+ return False
451
+
452
+ backend_port_str = _check_cancelled(
453
+ questionary.text(
454
+ "Backend port:",
455
+ default="8000",
456
+ validate=validate_port,
457
+ ).ask()
458
+ )
459
+
460
+ result = {"backend_port": int(backend_port_str)}
461
+
462
+ if has_frontend:
463
+ frontend_port_str = _check_cancelled(
464
+ questionary.text(
465
+ "Frontend port:",
466
+ default="3000",
467
+ validate=validate_port,
468
+ ).ask()
469
+ )
470
+ result["frontend_port"] = int(frontend_port_str)
471
+
472
+ return result
473
+
474
+
475
+ def run_interactive_prompts() -> ProjectConfig:
476
+ """Run all interactive prompts and return configuration."""
477
+ show_header()
478
+
479
+ # Basic info
480
+ basic_info = prompt_basic_info()
481
+
482
+ # Database
483
+ database = prompt_database()
484
+
485
+ # Auth
486
+ auth = prompt_auth()
487
+
488
+ # OAuth (only if JWT auth is enabled)
489
+ oauth_provider = OAuthProvider.NONE
490
+ enable_session_management = False
491
+ if auth in (AuthType.JWT, AuthType.BOTH):
492
+ oauth_provider = prompt_oauth()
493
+ # Session management (only if JWT and database enabled)
494
+ if database != DatabaseType.NONE:
495
+ enable_session_management = _check_cancelled(
496
+ questionary.confirm(
497
+ "Enable session management? (track active sessions, logout from devices)",
498
+ default=False,
499
+ ).ask()
500
+ )
501
+
502
+ # Logfire
503
+ enable_logfire, logfire_features = prompt_logfire()
504
+
505
+ # Background tasks
506
+ background_tasks = prompt_background_tasks()
507
+
508
+ # Integrations
509
+ integrations = prompt_integrations()
510
+
511
+ # Dev tools
512
+ dev_tools = prompt_dev_tools()
513
+
514
+ # Frontend
515
+ frontend = prompt_frontend()
516
+
517
+ # Python version
518
+ python_version = prompt_python_version()
519
+
520
+ # Port configuration
521
+ ports = prompt_ports(has_frontend=frontend != FrontendType.NONE)
522
+
523
+ # Auto-enable Redis for Celery/Taskiq/ARQ (they require Redis as broker)
524
+ if background_tasks in (
525
+ BackgroundTaskType.CELERY,
526
+ BackgroundTaskType.TASKIQ,
527
+ BackgroundTaskType.ARQ,
528
+ ):
529
+ integrations["enable_redis"] = True
530
+
531
+ # WebSocket auth and conversation persistence for AI Agent
532
+ websocket_auth = WebSocketAuthType.NONE
533
+ enable_conversation_persistence = False
534
+ if integrations.get("enable_ai_agent"):
535
+ websocket_auth = prompt_websocket_auth()
536
+ # Only offer persistence if database is enabled
537
+ if database != DatabaseType.NONE:
538
+ enable_conversation_persistence = _check_cancelled(
539
+ questionary.confirm(
540
+ "Enable conversation persistence (save chat history to database)?",
541
+ default=True,
542
+ ).ask()
543
+ )
544
+
545
+ # Admin panel configuration (when enabled and PostgreSQL)
546
+ admin_environments = AdminEnvironmentType.DEV_STAGING
547
+ admin_require_auth = True
548
+ if integrations.get("enable_admin_panel") and database == DatabaseType.POSTGRESQL:
549
+ admin_environments, admin_require_auth = prompt_admin_config()
550
+
551
+ # Frontend features (i18n, etc.)
552
+ frontend_features: dict[str, bool] = {}
553
+ if frontend != FrontendType.NONE:
554
+ frontend_features = prompt_frontend_features()
555
+
556
+ # Extract ci_type separately for type safety
557
+ ci_type = cast(CIType, dev_tools.pop("ci_type"))
558
+
559
+ # Build config
560
+ config = ProjectConfig(
561
+ project_name=basic_info["project_name"],
562
+ project_description=basic_info["project_description"],
563
+ author_name=basic_info["author_name"],
564
+ author_email=basic_info["author_email"],
565
+ database=database,
566
+ auth=auth,
567
+ oauth_provider=oauth_provider,
568
+ enable_session_management=enable_session_management,
569
+ enable_logfire=enable_logfire,
570
+ logfire_features=logfire_features,
571
+ background_tasks=background_tasks,
572
+ websocket_auth=websocket_auth,
573
+ enable_conversation_persistence=enable_conversation_persistence,
574
+ admin_environments=admin_environments,
575
+ admin_require_auth=admin_require_auth,
576
+ python_version=python_version,
577
+ ci_type=ci_type,
578
+ frontend=frontend,
579
+ backend_port=ports["backend_port"],
580
+ frontend_port=ports.get("frontend_port", 3000),
581
+ **integrations,
582
+ **dev_tools,
583
+ **frontend_features,
584
+ )
585
+
586
+ return config
587
+
588
+
589
+ def show_summary(config: ProjectConfig) -> None:
590
+ """Display configuration summary."""
591
+ console.print()
592
+ console.print("[bold green]Configuration Summary[/]")
593
+ console.print()
594
+
595
+ console.print(f" [cyan]Project:[/] {config.project_name}")
596
+ console.print(f" [cyan]Database:[/] {config.database.value}")
597
+ auth_str = config.auth.value
598
+ if config.oauth_provider != OAuthProvider.NONE:
599
+ auth_str += f" + {config.oauth_provider.value} OAuth"
600
+ console.print(f" [cyan]Auth:[/] {auth_str}")
601
+ console.print(f" [cyan]Logfire:[/] {'enabled' if config.enable_logfire else 'disabled'}")
602
+ console.print(f" [cyan]Background Tasks:[/] {config.background_tasks.value}")
603
+ console.print(f" [cyan]Frontend:[/] {config.frontend.value}")
604
+
605
+ enabled_features = []
606
+ if config.enable_redis:
607
+ enabled_features.append("Redis")
608
+ if config.enable_caching:
609
+ enabled_features.append("Caching")
610
+ if config.enable_rate_limiting:
611
+ enabled_features.append("Rate Limiting")
612
+ if config.enable_admin_panel:
613
+ admin_info = "Admin Panel"
614
+ if config.admin_environments.value != "all":
615
+ admin_info += f" ({config.admin_environments.value})"
616
+ if config.admin_require_auth:
617
+ admin_info += " [auth]"
618
+ enabled_features.append(admin_info)
619
+ if config.enable_websockets:
620
+ enabled_features.append("WebSockets")
621
+ if config.enable_ai_agent:
622
+ enabled_features.append("AI Agent")
623
+ if config.enable_webhooks:
624
+ enabled_features.append("Webhooks")
625
+ if config.enable_i18n:
626
+ enabled_features.append("i18n")
627
+ if config.include_example_crud:
628
+ enabled_features.append("Example CRUD")
629
+ if config.enable_docker:
630
+ enabled_features.append("Docker")
631
+
632
+ if enabled_features:
633
+ console.print(f" [cyan]Features:[/] {', '.join(enabled_features)}")
634
+
635
+ console.print()
636
+
637
+
638
+ def confirm_generation() -> bool:
639
+ """Confirm project generation."""
640
+ return cast(
641
+ bool,
642
+ _check_cancelled(
643
+ questionary.confirm(
644
+ "Generate project with this configuration?",
645
+ default=True,
646
+ ).ask()
647
+ ),
648
+ )