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.
- fastapi_fullstack-0.1.7.dist-info/METADATA +739 -0
- fastapi_fullstack-0.1.7.dist-info/RECORD +241 -0
- fastapi_fullstack-0.1.7.dist-info/WHEEL +4 -0
- fastapi_fullstack-0.1.7.dist-info/entry_points.txt +2 -0
- fastapi_fullstack-0.1.7.dist-info/licenses/LICENSE +21 -0
- fastapi_gen/__init__.py +3 -0
- fastapi_gen/cli.py +442 -0
- fastapi_gen/config.py +356 -0
- fastapi_gen/generator.py +207 -0
- fastapi_gen/prompts.py +874 -0
- fastapi_gen/template/VARIABLES.md +276 -0
- fastapi_gen/template/cookiecutter.json +93 -0
- fastapi_gen/template/hooks/post_gen_project.py +355 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.env.prod.example +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +150 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/.gitignore +109 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/AGENTS.md +55 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/CLAUDE.md +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/Makefile +315 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/README.md +768 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.dockerignore +60 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.env.example +155 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +32 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/Dockerfile +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +30 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/alembic.ini +48 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +3 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/admin.py +447 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +226 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +226 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +13 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +541 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +98 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +87 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +902 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +395 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +498 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +227 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +275 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +205 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +168 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +333 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +477 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +221 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +14 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +88 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +117 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +75 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +28 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +266 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +267 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +153 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +122 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +101 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +23 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +58 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +271 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +102 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +41 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +319 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +96 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +126 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +218 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +244 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +130 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/main.py +334 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +154 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +838 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +222 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +318 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +322 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +358 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +50 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +57 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +192 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +52 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +42 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +89 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +38 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +850 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +246 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +333 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +432 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +561 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +38 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +25 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +106 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +29 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +92 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +438 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +180 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +1 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +242 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +151 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +113 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +310 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +253 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +151 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +890 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +261 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +183 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +173 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +143 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +118 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +181 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +124 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +363 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +85 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +242 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +435 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docker-compose.yml +241 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/adding_features.md +132 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/architecture.md +63 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/patterns.md +161 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/docs/testing.md +120 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +40 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.env.example +12 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.gitignore +45 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +19 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/README.md +648 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +134 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +207 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +14 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +84 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +84 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/package.json +69 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +101 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +5 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +48 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +99 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +152 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +113 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +58 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +24 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +39 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +50 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +54 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +26 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +41 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +108 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +73 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +323 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +22 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +29 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +2 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +120 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +153 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +234 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +72 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +328 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +46 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +11 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +295 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +167 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +79 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +18 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +79 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +32 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +3 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +97 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +65 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +2 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +82 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +53 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +105 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +35 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +75 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +56 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +82 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +13 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +21 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +109 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +7 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +97 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +203 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +181 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +165 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +105 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +37 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +90 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +39 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +78 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +31 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +72 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +64 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +65 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +76 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +9 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +255 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +17 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +44 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +27 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +52 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +83 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +49 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +10 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +28 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +36 -0
- fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +56 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { Button, Card, CardHeader, CardTitle, CardContent } from "@/components/ui";
|
|
3
|
+
import { ROUTES } from "@/lib/constants";
|
|
4
|
+
|
|
5
|
+
export default function HomePage() {
|
|
6
|
+
return (
|
|
7
|
+
<div className="min-h-screen bg-background">
|
|
8
|
+
<div className="container mx-auto py-16 px-4">
|
|
9
|
+
<div className="text-center mb-12">
|
|
10
|
+
<h1 className="text-4xl font-bold mb-4">
|
|
11
|
+
{{ cookiecutter.project_name }}
|
|
12
|
+
</h1>
|
|
13
|
+
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
|
14
|
+
{{ cookiecutter.project_description }}
|
|
15
|
+
</p>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3 max-w-5xl mx-auto">
|
|
19
|
+
{% if cookiecutter.use_jwt %}
|
|
20
|
+
<Card>
|
|
21
|
+
<CardHeader>
|
|
22
|
+
<CardTitle>Authentication</CardTitle>
|
|
23
|
+
</CardHeader>
|
|
24
|
+
<CardContent>
|
|
25
|
+
<p className="mb-4 text-muted-foreground">
|
|
26
|
+
Secure JWT-based authentication system
|
|
27
|
+
</p>
|
|
28
|
+
<div className="flex gap-2">
|
|
29
|
+
<Button asChild>
|
|
30
|
+
<Link href={ROUTES.LOGIN}>Login</Link>
|
|
31
|
+
</Button>
|
|
32
|
+
<Button variant="outline" asChild>
|
|
33
|
+
<Link href={ROUTES.REGISTER}>Register</Link>
|
|
34
|
+
</Button>
|
|
35
|
+
</div>
|
|
36
|
+
</CardContent>
|
|
37
|
+
</Card>
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
40
|
+
{% if cookiecutter.enable_ai_agent %}
|
|
41
|
+
<Card>
|
|
42
|
+
<CardHeader>
|
|
43
|
+
<CardTitle>AI Assistant</CardTitle>
|
|
44
|
+
</CardHeader>
|
|
45
|
+
<CardContent>
|
|
46
|
+
<p className="mb-4 text-muted-foreground">
|
|
47
|
+
Chat with our AI assistant powered by PydanticAI
|
|
48
|
+
</p>
|
|
49
|
+
<Button asChild>
|
|
50
|
+
<Link href={ROUTES.CHAT}>Start Chat</Link>
|
|
51
|
+
</Button>
|
|
52
|
+
</CardContent>
|
|
53
|
+
</Card>
|
|
54
|
+
{% endif %}
|
|
55
|
+
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<CardTitle>Dashboard</CardTitle>
|
|
59
|
+
</CardHeader>
|
|
60
|
+
<CardContent>
|
|
61
|
+
<p className="mb-4 text-muted-foreground">
|
|
62
|
+
View your dashboard and manage your account
|
|
63
|
+
</p>
|
|
64
|
+
<Button variant="outline" asChild>
|
|
65
|
+
<Link href={ROUTES.DASHBOARD}>Go to Dashboard</Link>
|
|
66
|
+
</Button>
|
|
67
|
+
</CardContent>
|
|
68
|
+
</Card>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
3
|
+
import type { LoginResponse } from "@/types";
|
|
4
|
+
|
|
5
|
+
export async function POST(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const body = await request.json();
|
|
8
|
+
|
|
9
|
+
// Backend expects OAuth2 form data format
|
|
10
|
+
const formData = new URLSearchParams();
|
|
11
|
+
formData.append("username", body.email);
|
|
12
|
+
formData.append("password", body.password);
|
|
13
|
+
|
|
14
|
+
const data = await backendFetch<LoginResponse>("/api/v1/auth/login", {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
18
|
+
},
|
|
19
|
+
body: formData.toString(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Set HTTP-only cookies for tokens
|
|
23
|
+
const response = NextResponse.json({
|
|
24
|
+
user: data.user,
|
|
25
|
+
message: "Login successful",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Set access token cookie (short-lived)
|
|
29
|
+
response.cookies.set("access_token", data.access_token, {
|
|
30
|
+
httpOnly: true,
|
|
31
|
+
secure: process.env.NODE_ENV === "production",
|
|
32
|
+
sameSite: "lax",
|
|
33
|
+
maxAge: 60 * 15, // 15 minutes
|
|
34
|
+
path: "/",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Set refresh token cookie (long-lived)
|
|
38
|
+
response.cookies.set("refresh_token", data.refresh_token, {
|
|
39
|
+
httpOnly: true,
|
|
40
|
+
secure: process.env.NODE_ENV === "production",
|
|
41
|
+
sameSite: "lax",
|
|
42
|
+
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
43
|
+
path: "/",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return response;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (error instanceof BackendApiError) {
|
|
49
|
+
const detail =
|
|
50
|
+
(error.data as { detail?: string })?.detail || "Login failed";
|
|
51
|
+
return NextResponse.json({ detail }, { status: error.status });
|
|
52
|
+
}
|
|
53
|
+
return NextResponse.json(
|
|
54
|
+
{ detail: "Internal server error" },
|
|
55
|
+
{ status: 500 }
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}{% endraw %}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
export async function POST() {
|
|
4
|
+
const response = NextResponse.json({ message: "Logged out successfully" });
|
|
5
|
+
|
|
6
|
+
// Clear auth cookies
|
|
7
|
+
response.cookies.set("access_token", "", {
|
|
8
|
+
httpOnly: true,
|
|
9
|
+
secure: process.env.NODE_ENV === "production",
|
|
10
|
+
sameSite: "lax",
|
|
11
|
+
maxAge: 0,
|
|
12
|
+
path: "/",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
response.cookies.set("refresh_token", "", {
|
|
16
|
+
httpOnly: true,
|
|
17
|
+
secure: process.env.NODE_ENV === "production",
|
|
18
|
+
sameSite: "lax",
|
|
19
|
+
maxAge: 0,
|
|
20
|
+
path: "/",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return response;
|
|
24
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
3
|
+
import type { User } from "@/types";
|
|
4
|
+
|
|
5
|
+
export async function GET(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
8
|
+
|
|
9
|
+
if (!accessToken) {
|
|
10
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const data = await backendFetch<User>("/api/v1/auth/me", {
|
|
14
|
+
headers: {
|
|
15
|
+
Authorization: `Bearer ${accessToken}`,
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
return NextResponse.json(data);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (error instanceof BackendApiError) {
|
|
22
|
+
if (error.status === 401) {
|
|
23
|
+
// Token expired, try to refresh
|
|
24
|
+
return NextResponse.json(
|
|
25
|
+
{ detail: "Token expired" },
|
|
26
|
+
{ status: 401 }
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return NextResponse.json(
|
|
30
|
+
{ detail: "Failed to get user" },
|
|
31
|
+
{ status: error.status }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return NextResponse.json(
|
|
35
|
+
{ detail: "Internal server error" },
|
|
36
|
+
{ status: 500 }
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
}{% endraw %}
|
fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{%- if cookiecutter.enable_oauth %}
|
|
2
|
+
import { cookies } from "next/headers";
|
|
3
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
4
|
+
|
|
5
|
+
export async function POST(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const { accessToken, refreshToken } = await request.json();
|
|
8
|
+
|
|
9
|
+
if (!accessToken || !refreshToken) {
|
|
10
|
+
return NextResponse.json(
|
|
11
|
+
{ error: "Missing tokens" },
|
|
12
|
+
{ status: 400 }
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const cookieStore = await cookies();
|
|
17
|
+
|
|
18
|
+
// Set access token cookie
|
|
19
|
+
cookieStore.set("access_token", accessToken, {
|
|
20
|
+
httpOnly: true,
|
|
21
|
+
secure: process.env.NODE_ENV === "production",
|
|
22
|
+
sameSite: "lax",
|
|
23
|
+
maxAge: 60 * 60 * 24, // 24 hours
|
|
24
|
+
path: "/",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Set refresh token cookie
|
|
28
|
+
cookieStore.set("refresh_token", refreshToken, {
|
|
29
|
+
httpOnly: true,
|
|
30
|
+
secure: process.env.NODE_ENV === "production",
|
|
31
|
+
sameSite: "lax",
|
|
32
|
+
maxAge: 60 * 60 * 24 * 7, // 7 days
|
|
33
|
+
path: "/",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return NextResponse.json({ success: true });
|
|
37
|
+
} catch {
|
|
38
|
+
return NextResponse.json(
|
|
39
|
+
{ error: "Failed to process OAuth callback" },
|
|
40
|
+
{ status: 500 }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
{%- else %}
|
|
45
|
+
import { NextResponse } from "next/server";
|
|
46
|
+
|
|
47
|
+
export async function POST() {
|
|
48
|
+
return NextResponse.json({ error: "OAuth not enabled" }, { status: 404 });
|
|
49
|
+
}
|
|
50
|
+
{%- endif %}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
3
|
+
import type { RefreshTokenResponse } from "@/types";
|
|
4
|
+
|
|
5
|
+
export async function POST(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const refreshToken = request.cookies.get("refresh_token")?.value;
|
|
8
|
+
|
|
9
|
+
if (!refreshToken) {
|
|
10
|
+
return NextResponse.json(
|
|
11
|
+
{ detail: "No refresh token" },
|
|
12
|
+
{ status: 401 }
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const data = await backendFetch<RefreshTokenResponse>(
|
|
17
|
+
"/api/v1/auth/refresh",
|
|
18
|
+
{
|
|
19
|
+
method: "POST",
|
|
20
|
+
body: JSON.stringify({ refresh_token: refreshToken }),
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const response = NextResponse.json({ message: "Token refreshed" });
|
|
25
|
+
|
|
26
|
+
// Update access token cookie
|
|
27
|
+
response.cookies.set("access_token", data.access_token, {
|
|
28
|
+
httpOnly: true,
|
|
29
|
+
secure: process.env.NODE_ENV === "production",
|
|
30
|
+
sameSite: "lax",
|
|
31
|
+
maxAge: 60 * 15, // 15 minutes
|
|
32
|
+
path: "/",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return response;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof BackendApiError) {
|
|
38
|
+
// Clear cookies on refresh failure
|
|
39
|
+
const response = NextResponse.json(
|
|
40
|
+
{ detail: "Session expired" },
|
|
41
|
+
{ status: 401 }
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
response.cookies.set("access_token", "", { maxAge: 0, path: "/" });
|
|
45
|
+
response.cookies.set("refresh_token", "", { maxAge: 0, path: "/" });
|
|
46
|
+
|
|
47
|
+
return response;
|
|
48
|
+
}
|
|
49
|
+
return NextResponse.json(
|
|
50
|
+
{ detail: "Internal server error" },
|
|
51
|
+
{ status: 500 }
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}{% endraw %}
|
fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
3
|
+
import type { RegisterResponse } from "@/types";
|
|
4
|
+
|
|
5
|
+
export async function POST(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const body = await request.json();
|
|
8
|
+
|
|
9
|
+
const data = await backendFetch<RegisterResponse>("/api/v1/auth/register", {
|
|
10
|
+
method: "POST",
|
|
11
|
+
body: JSON.stringify(body),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return NextResponse.json(data, { status: 201 });
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error instanceof BackendApiError) {
|
|
17
|
+
const detail =
|
|
18
|
+
(error.data as { detail?: string })?.detail || "Registration failed";
|
|
19
|
+
return NextResponse.json({ detail }, { status: error.status });
|
|
20
|
+
}
|
|
21
|
+
return NextResponse.json(
|
|
22
|
+
{ detail: "Internal server error" },
|
|
23
|
+
{ status: 500 }
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
}{% endraw %}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{%- if cookiecutter.enable_conversation_persistence and cookiecutter.use_database %}
|
|
2
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
3
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
4
|
+
|
|
5
|
+
interface RouteParams {
|
|
6
|
+
params: Promise<{ id: string }>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function GET(request: NextRequest, { params }: RouteParams) {
|
|
10
|
+
try {
|
|
11
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
12
|
+
|
|
13
|
+
if (!accessToken) {
|
|
14
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { id } = await params;
|
|
18
|
+
|
|
19
|
+
const data = await backendFetch(`/api/v1/conversations/${id}/messages`, {
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${accessToken}`,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return NextResponse.json(data);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (error instanceof BackendApiError) {
|
|
28
|
+
return NextResponse.json(
|
|
29
|
+
{ detail: error.message || "Failed to fetch messages" },
|
|
30
|
+
{ status: error.status }
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ detail: "Internal server error" },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}{% endraw %}
|
|
39
|
+
{%- else %}
|
|
40
|
+
// Conversation messages API route - not configured (enable_conversation_persistence is false)
|
|
41
|
+
{%- endif %}
|
fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{%- if cookiecutter.enable_conversation_persistence and cookiecutter.use_database %}
|
|
2
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
3
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
4
|
+
|
|
5
|
+
interface RouteParams {
|
|
6
|
+
params: Promise<{ id: string }>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function GET(request: NextRequest, { params }: RouteParams) {
|
|
10
|
+
try {
|
|
11
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
12
|
+
|
|
13
|
+
if (!accessToken) {
|
|
14
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { id } = await params;
|
|
18
|
+
|
|
19
|
+
const data = await backendFetch(`/api/v1/conversations/${id}`, {
|
|
20
|
+
headers: {
|
|
21
|
+
Authorization: `Bearer ${accessToken}`,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return NextResponse.json(data);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (error instanceof BackendApiError) {
|
|
28
|
+
return NextResponse.json(
|
|
29
|
+
{ detail: error.message || "Failed to fetch conversation" },
|
|
30
|
+
{ status: error.status }
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return NextResponse.json(
|
|
34
|
+
{ detail: "Internal server error" },
|
|
35
|
+
{ status: 500 }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function PATCH(request: NextRequest, { params }: RouteParams) {
|
|
41
|
+
try {
|
|
42
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
43
|
+
|
|
44
|
+
if (!accessToken) {
|
|
45
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { id } = await params;
|
|
49
|
+
const body = await request.json();
|
|
50
|
+
|
|
51
|
+
const data = await backendFetch(`/api/v1/conversations/${id}`, {
|
|
52
|
+
method: "PATCH",
|
|
53
|
+
headers: {
|
|
54
|
+
Authorization: `Bearer ${accessToken}`,
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify(body),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return NextResponse.json(data);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof BackendApiError) {
|
|
63
|
+
return NextResponse.json(
|
|
64
|
+
{ detail: error.message || "Failed to update conversation" },
|
|
65
|
+
{ status: error.status }
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return NextResponse.json(
|
|
69
|
+
{ detail: "Internal server error" },
|
|
70
|
+
{ status: 500 }
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function DELETE(request: NextRequest, { params }: RouteParams) {
|
|
76
|
+
try {
|
|
77
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
78
|
+
|
|
79
|
+
if (!accessToken) {
|
|
80
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const { id } = await params;
|
|
84
|
+
|
|
85
|
+
await backendFetch(`/api/v1/conversations/${id}`, {
|
|
86
|
+
method: "DELETE",
|
|
87
|
+
headers: {
|
|
88
|
+
Authorization: `Bearer ${accessToken}`,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return new NextResponse(null, { status: 204 });
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof BackendApiError) {
|
|
95
|
+
return NextResponse.json(
|
|
96
|
+
{ detail: error.message || "Failed to delete conversation" },
|
|
97
|
+
{ status: error.status }
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return NextResponse.json(
|
|
101
|
+
{ detail: "Internal server error" },
|
|
102
|
+
{ status: 500 }
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}{% endraw %}
|
|
106
|
+
{%- else %}
|
|
107
|
+
// Conversation detail API route - not configured (enable_conversation_persistence is false)
|
|
108
|
+
{%- endif %}
|
fastapi_gen/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{%- if cookiecutter.enable_conversation_persistence and cookiecutter.use_database %}
|
|
2
|
+
{% raw %}import { NextRequest, NextResponse } from "next/server";
|
|
3
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
4
|
+
|
|
5
|
+
export async function GET(request: NextRequest) {
|
|
6
|
+
try {
|
|
7
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
8
|
+
|
|
9
|
+
if (!accessToken) {
|
|
10
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const searchParams = request.nextUrl.searchParams;
|
|
14
|
+
const skip = searchParams.get("skip") || "0";
|
|
15
|
+
const limit = searchParams.get("limit") || "50";
|
|
16
|
+
|
|
17
|
+
const data = await backendFetch(`/api/v1/conversations?skip=${skip}&limit=${limit}`, {
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${accessToken}`,
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return NextResponse.json(data);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error instanceof BackendApiError) {
|
|
26
|
+
return NextResponse.json(
|
|
27
|
+
{ detail: error.message || "Failed to fetch conversations" },
|
|
28
|
+
{ status: error.status }
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return NextResponse.json(
|
|
32
|
+
{ detail: "Internal server error" },
|
|
33
|
+
{ status: 500 }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function POST(request: NextRequest) {
|
|
39
|
+
try {
|
|
40
|
+
const accessToken = request.cookies.get("access_token")?.value;
|
|
41
|
+
|
|
42
|
+
if (!accessToken) {
|
|
43
|
+
return NextResponse.json({ detail: "Not authenticated" }, { status: 401 });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const body = await request.json();
|
|
47
|
+
|
|
48
|
+
const data = await backendFetch("/api/v1/conversations", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${accessToken}`,
|
|
52
|
+
"Content-Type": "application/json",
|
|
53
|
+
},
|
|
54
|
+
body: JSON.stringify(body),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return NextResponse.json(data, { status: 201 });
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof BackendApiError) {
|
|
60
|
+
return NextResponse.json(
|
|
61
|
+
{ detail: error.message || "Failed to create conversation" },
|
|
62
|
+
{ status: error.status }
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return NextResponse.json(
|
|
66
|
+
{ detail: "Internal server error" },
|
|
67
|
+
{ status: 500 }
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}{% endraw %}
|
|
71
|
+
{%- else %}
|
|
72
|
+
// Conversations API route - not configured (enable_conversation_persistence is false)
|
|
73
|
+
{%- endif %}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { backendFetch, BackendApiError } from "@/lib/server-api";
|
|
3
|
+
import type { HealthResponse } from "@/types";
|
|
4
|
+
|
|
5
|
+
export async function GET() {
|
|
6
|
+
try {
|
|
7
|
+
const data = await backendFetch<HealthResponse>("/api/v1/health");
|
|
8
|
+
return NextResponse.json(data);
|
|
9
|
+
} catch (error) {
|
|
10
|
+
if (error instanceof BackendApiError) {
|
|
11
|
+
return NextResponse.json(
|
|
12
|
+
{ detail: "Backend service unavailable" },
|
|
13
|
+
{ status: error.status }
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
return NextResponse.json(
|
|
17
|
+
{ detail: "Internal server error" },
|
|
18
|
+
{ status: 500 }
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|