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,132 @@
|
|
|
1
|
+
# Adding New Features
|
|
2
|
+
|
|
3
|
+
## Adding a New API Endpoint
|
|
4
|
+
|
|
5
|
+
1. **Create schema** in `schemas/`
|
|
6
|
+
```python
|
|
7
|
+
# schemas/item.py
|
|
8
|
+
class ItemCreate(BaseModel):
|
|
9
|
+
name: str
|
|
10
|
+
description: str | None = None
|
|
11
|
+
|
|
12
|
+
class ItemResponse(BaseModel):
|
|
13
|
+
id: UUID
|
|
14
|
+
name: str
|
|
15
|
+
created_at: datetime
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. **Create model** in `db/models/` (if new entity)
|
|
19
|
+
```python
|
|
20
|
+
# db/models/item.py
|
|
21
|
+
class Item(Base):
|
|
22
|
+
__tablename__ = "items"
|
|
23
|
+
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
|
24
|
+
name: Mapped[str] = mapped_column(String(255))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
3. **Create repository** in `repositories/`
|
|
28
|
+
```python
|
|
29
|
+
# repositories/item.py
|
|
30
|
+
class ItemRepository:
|
|
31
|
+
async def create(self, db: AsyncSession, **kwargs) -> Item:
|
|
32
|
+
item = Item(**kwargs)
|
|
33
|
+
db.add(item)
|
|
34
|
+
await db.flush()
|
|
35
|
+
await db.refresh(item)
|
|
36
|
+
return item
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
4. **Create service** in `services/`
|
|
40
|
+
```python
|
|
41
|
+
# services/item.py
|
|
42
|
+
class ItemService:
|
|
43
|
+
def __init__(self, db: AsyncSession):
|
|
44
|
+
self.db = db
|
|
45
|
+
self.repo = ItemRepository()
|
|
46
|
+
|
|
47
|
+
async def create(self, item_in: ItemCreate) -> Item:
|
|
48
|
+
return await self.repo.create(self.db, **item_in.model_dump())
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
5. **Create route** in `api/routes/v1/`
|
|
52
|
+
```python
|
|
53
|
+
# api/routes/v1/items.py
|
|
54
|
+
router = APIRouter(prefix="/items", tags=["items"])
|
|
55
|
+
|
|
56
|
+
@router.post("/", response_model=ItemResponse, status_code=201)
|
|
57
|
+
async def create_item(
|
|
58
|
+
item_in: ItemCreate,
|
|
59
|
+
db: AsyncSession = Depends(get_db),
|
|
60
|
+
):
|
|
61
|
+
service = ItemService(db)
|
|
62
|
+
return await service.create(item_in)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
6. **Register route** in `api/routes/v1/__init__.py`
|
|
66
|
+
```python
|
|
67
|
+
from .items import router as items_router
|
|
68
|
+
api_router.include_router(items_router)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Adding a Custom CLI Command
|
|
72
|
+
|
|
73
|
+
Commands are auto-discovered from `app/commands/`.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
# app/commands/my_command.py
|
|
77
|
+
from app.commands import command, success, error
|
|
78
|
+
import click
|
|
79
|
+
|
|
80
|
+
@command("my-command", help="Description of what this does")
|
|
81
|
+
@click.option("--name", "-n", required=True, help="Name parameter")
|
|
82
|
+
def my_command(name: str):
|
|
83
|
+
# Your logic here
|
|
84
|
+
success(f"Done: {name}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run with: `uv run {{ cookiecutter.project_slug }} cmd my-command --name test`
|
|
88
|
+
{%- if cookiecutter.enable_ai_agent and cookiecutter.use_pydantic_ai %}
|
|
89
|
+
|
|
90
|
+
## Adding an AI Agent Tool (PydanticAI)
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
# app/agents/assistant.py
|
|
94
|
+
@agent.tool
|
|
95
|
+
async def my_tool(ctx: RunContext[Deps], param: str) -> dict:
|
|
96
|
+
"""Tool description for LLM - be specific about what it does."""
|
|
97
|
+
# Access dependencies via ctx.deps
|
|
98
|
+
result = await some_operation(param)
|
|
99
|
+
return {"result": result}
|
|
100
|
+
```
|
|
101
|
+
{%- endif %}
|
|
102
|
+
{%- if cookiecutter.enable_ai_agent and cookiecutter.use_langchain %}
|
|
103
|
+
|
|
104
|
+
## Adding an AI Agent Tool (LangChain)
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# app/agents/langchain_assistant.py
|
|
108
|
+
from langchain.tools import tool
|
|
109
|
+
|
|
110
|
+
@tool
|
|
111
|
+
def my_tool(param: str) -> dict:
|
|
112
|
+
"""Tool description for LLM - be specific about what it does."""
|
|
113
|
+
result = some_operation(param)
|
|
114
|
+
return {"result": result}
|
|
115
|
+
```
|
|
116
|
+
{%- endif %}
|
|
117
|
+
{%- if cookiecutter.use_postgresql or cookiecutter.use_sqlite %}
|
|
118
|
+
|
|
119
|
+
## Adding a Database Migration
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# Create migration
|
|
123
|
+
uv run alembic revision --autogenerate -m "Add items table"
|
|
124
|
+
|
|
125
|
+
# Apply migration
|
|
126
|
+
uv run alembic upgrade head
|
|
127
|
+
|
|
128
|
+
# Or use CLI
|
|
129
|
+
uv run {{ cookiecutter.project_slug }} db migrate -m "Add items table"
|
|
130
|
+
uv run {{ cookiecutter.project_slug }} db upgrade
|
|
131
|
+
```
|
|
132
|
+
{%- endif %}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Architecture Guide
|
|
2
|
+
|
|
3
|
+
This project follows a **Repository + Service** layered architecture.
|
|
4
|
+
|
|
5
|
+
## Request Flow
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
HTTP Request → API Route → Service → Repository → Database
|
|
9
|
+
↓
|
|
10
|
+
Response ← Service ← Repository ←
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Directory Structure (`backend/app/`)
|
|
14
|
+
|
|
15
|
+
| Directory | Purpose |
|
|
16
|
+
|-----------|---------|
|
|
17
|
+
| `api/routes/v1/` | HTTP endpoints, request validation, auth |
|
|
18
|
+
| `api/deps.py` | Dependency injection (db session, current user) |
|
|
19
|
+
| `services/` | Business logic, orchestration |
|
|
20
|
+
| `repositories/` | Data access layer, database queries |
|
|
21
|
+
| `schemas/` | Pydantic models for request/response |
|
|
22
|
+
| `db/models/` | SQLAlchemy/MongoDB models |
|
|
23
|
+
| `core/config.py` | Settings via pydantic-settings |
|
|
24
|
+
{%- if cookiecutter.use_auth %}
|
|
25
|
+
| `core/security.py` | JWT/API key utilities |
|
|
26
|
+
{%- endif %}
|
|
27
|
+
{%- if cookiecutter.enable_ai_agent %}
|
|
28
|
+
| `agents/` | AI agents and tools |
|
|
29
|
+
{%- endif %}
|
|
30
|
+
| `commands/` | Django-style CLI commands |
|
|
31
|
+
{%- if cookiecutter.use_celery or cookiecutter.use_taskiq %}
|
|
32
|
+
| `worker/` | Background task definitions |
|
|
33
|
+
{%- endif %}
|
|
34
|
+
|
|
35
|
+
## Layer Responsibilities
|
|
36
|
+
|
|
37
|
+
### API Routes (`api/routes/v1/`)
|
|
38
|
+
- HTTP request/response handling
|
|
39
|
+
- Input validation via Pydantic schemas
|
|
40
|
+
- Authentication/authorization checks
|
|
41
|
+
- Delegates to services for business logic
|
|
42
|
+
|
|
43
|
+
### Services (`services/`)
|
|
44
|
+
- Business logic and validation
|
|
45
|
+
- Orchestrates repository calls
|
|
46
|
+
- Raises domain exceptions (NotFoundError, etc.)
|
|
47
|
+
- Transaction boundaries
|
|
48
|
+
|
|
49
|
+
### Repositories (`repositories/`)
|
|
50
|
+
- Database operations only
|
|
51
|
+
- No business logic
|
|
52
|
+
- Uses `db.flush()` not `commit()` (let dependency manage transactions)
|
|
53
|
+
- Returns domain models
|
|
54
|
+
|
|
55
|
+
## Key Files
|
|
56
|
+
|
|
57
|
+
- Entry point: `app/main.py`
|
|
58
|
+
- Configuration: `app/core/config.py`
|
|
59
|
+
- Dependencies: `app/api/deps.py`
|
|
60
|
+
{%- if cookiecutter.use_auth %}
|
|
61
|
+
- Auth utilities: `app/core/security.py`
|
|
62
|
+
{%- endif %}
|
|
63
|
+
- Exception handlers: `app/api/exception_handlers.py`
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Code Patterns
|
|
2
|
+
|
|
3
|
+
## Dependency Injection
|
|
4
|
+
|
|
5
|
+
Use FastAPI's `Depends()` for injecting dependencies:
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
from app.api.deps import get_db, get_current_user
|
|
9
|
+
|
|
10
|
+
@router.get("/items")
|
|
11
|
+
async def list_items(
|
|
12
|
+
db: AsyncSession = Depends(get_db),
|
|
13
|
+
current_user: User = Depends(get_current_user),
|
|
14
|
+
):
|
|
15
|
+
service = ItemService(db)
|
|
16
|
+
return await service.get_multi()
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Available dependencies in `app/api/deps.py`:
|
|
20
|
+
- `get_db` - Database session
|
|
21
|
+
{%- if cookiecutter.use_auth %}
|
|
22
|
+
- `get_current_user` - Authenticated user (raises 401 if not authenticated)
|
|
23
|
+
- `get_current_user_optional` - User or None
|
|
24
|
+
{%- endif %}
|
|
25
|
+
{%- if cookiecutter.enable_redis %}
|
|
26
|
+
- `get_redis` - Redis connection
|
|
27
|
+
{%- endif %}
|
|
28
|
+
|
|
29
|
+
## Service Layer Pattern
|
|
30
|
+
|
|
31
|
+
Services contain business logic:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
class ItemService:
|
|
35
|
+
def __init__(self, db: AsyncSession):
|
|
36
|
+
self.db = db
|
|
37
|
+
self.repo = ItemRepository()
|
|
38
|
+
|
|
39
|
+
async def create(self, item_in: ItemCreate) -> Item:
|
|
40
|
+
# Business validation
|
|
41
|
+
if await self.repo.exists_by_name(self.db, item_in.name):
|
|
42
|
+
raise AlreadyExistsError(message="Item already exists")
|
|
43
|
+
|
|
44
|
+
# Create via repository
|
|
45
|
+
return await self.repo.create(self.db, **item_in.model_dump())
|
|
46
|
+
|
|
47
|
+
async def get_or_raise(self, id: UUID) -> Item:
|
|
48
|
+
item = await self.repo.get_by_id(self.db, id)
|
|
49
|
+
if not item:
|
|
50
|
+
raise NotFoundError(message="Item not found", details={"id": str(id)})
|
|
51
|
+
return item
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Repository Layer Pattern
|
|
55
|
+
|
|
56
|
+
Repositories handle data access only:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
class ItemRepository:
|
|
60
|
+
async def get_by_id(self, db: AsyncSession, id: UUID) -> Item | None:
|
|
61
|
+
return await db.get(Item, id)
|
|
62
|
+
|
|
63
|
+
async def create(self, db: AsyncSession, **kwargs) -> Item:
|
|
64
|
+
item = Item(**kwargs)
|
|
65
|
+
db.add(item)
|
|
66
|
+
await db.flush() # Not commit! Let dependency manage transaction
|
|
67
|
+
await db.refresh(item)
|
|
68
|
+
return item
|
|
69
|
+
|
|
70
|
+
async def get_multi(
|
|
71
|
+
self, db: AsyncSession, skip: int = 0, limit: int = 100
|
|
72
|
+
) -> list[Item]:
|
|
73
|
+
result = await db.execute(
|
|
74
|
+
select(Item).offset(skip).limit(limit)
|
|
75
|
+
)
|
|
76
|
+
return list(result.scalars().all())
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Exception Handling
|
|
80
|
+
|
|
81
|
+
Use domain exceptions in services:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from app.core.exceptions import NotFoundError, AlreadyExistsError, ValidationError
|
|
85
|
+
|
|
86
|
+
# In service
|
|
87
|
+
if not item:
|
|
88
|
+
raise NotFoundError(
|
|
89
|
+
message="Item not found",
|
|
90
|
+
details={"id": str(id)}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if await self.repo.exists_by_email(self.db, email):
|
|
94
|
+
raise AlreadyExistsError(
|
|
95
|
+
message="User with this email already exists"
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Exception handlers convert to HTTP responses automatically.
|
|
100
|
+
|
|
101
|
+
## Schema Patterns
|
|
102
|
+
|
|
103
|
+
Separate schemas for different operations:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
# Base with shared fields
|
|
107
|
+
class ItemBase(BaseModel):
|
|
108
|
+
name: str
|
|
109
|
+
description: str | None = None
|
|
110
|
+
|
|
111
|
+
# For creation (input)
|
|
112
|
+
class ItemCreate(ItemBase):
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
# For updates (all optional)
|
|
116
|
+
class ItemUpdate(BaseModel):
|
|
117
|
+
name: str | None = None
|
|
118
|
+
description: str | None = None
|
|
119
|
+
|
|
120
|
+
# For responses (with DB fields)
|
|
121
|
+
class ItemResponse(ItemBase):
|
|
122
|
+
id: UUID
|
|
123
|
+
created_at: datetime
|
|
124
|
+
updated_at: datetime | None
|
|
125
|
+
|
|
126
|
+
model_config = ConfigDict(from_attributes=True)
|
|
127
|
+
```
|
|
128
|
+
{%- if cookiecutter.use_frontend %}
|
|
129
|
+
|
|
130
|
+
## Frontend Patterns
|
|
131
|
+
|
|
132
|
+
### Authentication (HTTP-only cookies)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { useAuth } from '@/hooks/use-auth';
|
|
136
|
+
|
|
137
|
+
function Component() {
|
|
138
|
+
const { user, isAuthenticated, login, logout } = useAuth();
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### State Management (Zustand)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { useAuthStore } from '@/stores/auth-store';
|
|
146
|
+
|
|
147
|
+
const { user, setUser, logout } = useAuthStore();
|
|
148
|
+
```
|
|
149
|
+
{%- if cookiecutter.enable_ai_agent %}
|
|
150
|
+
|
|
151
|
+
### WebSocket Chat
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { useChat } from '@/hooks/use-chat';
|
|
155
|
+
|
|
156
|
+
function ChatPage() {
|
|
157
|
+
const { messages, sendMessage, isStreaming } = useChat();
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
{%- endif %}
|
|
161
|
+
{%- endif %}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Testing Guide
|
|
2
|
+
|
|
3
|
+
## Running Tests
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cd backend
|
|
7
|
+
|
|
8
|
+
# Run all tests
|
|
9
|
+
pytest
|
|
10
|
+
|
|
11
|
+
# Run with coverage
|
|
12
|
+
pytest --cov=app --cov-report=term-missing
|
|
13
|
+
|
|
14
|
+
# Run specific test file
|
|
15
|
+
pytest tests/api/test_health.py -v
|
|
16
|
+
|
|
17
|
+
# Run specific test
|
|
18
|
+
pytest tests/api/test_health.py::test_health_check -v
|
|
19
|
+
|
|
20
|
+
# Run only unit tests
|
|
21
|
+
pytest tests/unit/
|
|
22
|
+
|
|
23
|
+
# Run only integration tests
|
|
24
|
+
pytest tests/integration/
|
|
25
|
+
|
|
26
|
+
# Run with verbose output
|
|
27
|
+
pytest -v
|
|
28
|
+
|
|
29
|
+
# Stop on first failure
|
|
30
|
+
pytest -x
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Test Structure
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
tests/
|
|
37
|
+
├── conftest.py # Shared fixtures
|
|
38
|
+
├── api/ # API endpoint tests
|
|
39
|
+
│ ├── test_health.py
|
|
40
|
+
│ └── test_auth.py
|
|
41
|
+
├── unit/ # Unit tests (services, utils)
|
|
42
|
+
│ └── test_services.py
|
|
43
|
+
└── integration/ # Integration tests
|
|
44
|
+
└── test_db.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Key Fixtures (`conftest.py`)
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
# Database session for tests
|
|
51
|
+
@pytest.fixture
|
|
52
|
+
async def db_session():
|
|
53
|
+
async with async_session() as session:
|
|
54
|
+
yield session
|
|
55
|
+
await session.rollback()
|
|
56
|
+
|
|
57
|
+
# Test client
|
|
58
|
+
@pytest.fixture
|
|
59
|
+
def client():
|
|
60
|
+
return TestClient(app)
|
|
61
|
+
|
|
62
|
+
# Authenticated client
|
|
63
|
+
@pytest.fixture
|
|
64
|
+
async def auth_client(client, test_user):
|
|
65
|
+
token = create_access_token(test_user.id)
|
|
66
|
+
client.headers["Authorization"] = f"Bearer {token}"
|
|
67
|
+
return client
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Writing Tests
|
|
71
|
+
|
|
72
|
+
### API Endpoint Test
|
|
73
|
+
```python
|
|
74
|
+
def test_health_check(client):
|
|
75
|
+
response = client.get("/api/v1/health")
|
|
76
|
+
assert response.status_code == 200
|
|
77
|
+
assert response.json()["status"] == "healthy"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Service Test
|
|
81
|
+
```python
|
|
82
|
+
async def test_create_item(db_session):
|
|
83
|
+
service = ItemService(db_session)
|
|
84
|
+
item = await service.create(ItemCreate(name="Test"))
|
|
85
|
+
assert item.name == "Test"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Test with Authentication
|
|
89
|
+
```python
|
|
90
|
+
def test_protected_endpoint(auth_client):
|
|
91
|
+
response = auth_client.get("/api/v1/users/me")
|
|
92
|
+
assert response.status_code == 200
|
|
93
|
+
```
|
|
94
|
+
{%- if cookiecutter.use_frontend %}
|
|
95
|
+
|
|
96
|
+
## Frontend Tests
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
cd frontend
|
|
100
|
+
|
|
101
|
+
# Run unit tests
|
|
102
|
+
bun test
|
|
103
|
+
|
|
104
|
+
# Run with watch mode
|
|
105
|
+
bun test --watch
|
|
106
|
+
|
|
107
|
+
# Run E2E tests
|
|
108
|
+
bun test:e2e
|
|
109
|
+
|
|
110
|
+
# Run E2E in headed mode (see browser)
|
|
111
|
+
bun test:e2e --headed
|
|
112
|
+
```
|
|
113
|
+
{%- endif %}
|
|
114
|
+
|
|
115
|
+
## Test Database
|
|
116
|
+
|
|
117
|
+
Tests use a separate test database or SQLite in-memory:
|
|
118
|
+
- Configuration in `tests/conftest.py`
|
|
119
|
+
- Database is reset between tests
|
|
120
|
+
- Use fixtures for test data
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Build outputs
|
|
7
|
+
.next
|
|
8
|
+
out
|
|
9
|
+
build
|
|
10
|
+
dist
|
|
11
|
+
|
|
12
|
+
# Testing
|
|
13
|
+
coverage
|
|
14
|
+
.nyc_output
|
|
15
|
+
|
|
16
|
+
# Debug
|
|
17
|
+
npm-debug.log*
|
|
18
|
+
yarn-debug.log*
|
|
19
|
+
yarn-error.log*
|
|
20
|
+
|
|
21
|
+
# Local env files
|
|
22
|
+
.env
|
|
23
|
+
.env.local
|
|
24
|
+
.env.development.local
|
|
25
|
+
.env.test.local
|
|
26
|
+
.env.production.local
|
|
27
|
+
|
|
28
|
+
# IDE
|
|
29
|
+
.idea
|
|
30
|
+
.vscode
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# OS
|
|
35
|
+
.DS_Store
|
|
36
|
+
Thumbs.db
|
|
37
|
+
|
|
38
|
+
# Misc
|
|
39
|
+
*.log
|
|
40
|
+
.turbo
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Backend API URL (server-side only - not exposed to browser)
|
|
2
|
+
BACKEND_URL=http://localhost:{{ cookiecutter.backend_port }}
|
|
3
|
+
|
|
4
|
+
# WebSocket URL for real-time features
|
|
5
|
+
BACKEND_WS_URL=ws://localhost:{{ cookiecutter.backend_port }}
|
|
6
|
+
{%- if cookiecutter.enable_logfire %}
|
|
7
|
+
|
|
8
|
+
# Logfire/OpenTelemetry (server-side instrumentation)
|
|
9
|
+
# Get your write token from: https://logfire.pydantic.dev
|
|
10
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=https://logfire-api.pydantic.dev
|
|
11
|
+
OTEL_EXPORTER_OTLP_HEADERS=Authorization=your-logfire-write-token
|
|
12
|
+
{%- endif %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules
|
|
3
|
+
.pnp
|
|
4
|
+
.pnp.js
|
|
5
|
+
|
|
6
|
+
# Testing
|
|
7
|
+
coverage
|
|
8
|
+
|
|
9
|
+
# Playwright
|
|
10
|
+
/test-results/
|
|
11
|
+
/playwright-report/
|
|
12
|
+
/blob-report/
|
|
13
|
+
/playwright/.cache/
|
|
14
|
+
.playwright/
|
|
15
|
+
|
|
16
|
+
# Next.js
|
|
17
|
+
.next/
|
|
18
|
+
out/
|
|
19
|
+
build
|
|
20
|
+
|
|
21
|
+
# Misc
|
|
22
|
+
.DS_Store
|
|
23
|
+
*.pem
|
|
24
|
+
|
|
25
|
+
# Debug
|
|
26
|
+
npm-debug.log*
|
|
27
|
+
yarn-debug.log*
|
|
28
|
+
yarn-error.log*
|
|
29
|
+
|
|
30
|
+
# Local env files
|
|
31
|
+
.env
|
|
32
|
+
.env.local
|
|
33
|
+
.env.development.local
|
|
34
|
+
.env.test.local
|
|
35
|
+
.env.production.local
|
|
36
|
+
|
|
37
|
+
# Vercel
|
|
38
|
+
.vercel
|
|
39
|
+
|
|
40
|
+
# TypeScript
|
|
41
|
+
*.tsbuildinfo
|
|
42
|
+
next-env.d.ts
|
|
43
|
+
|
|
44
|
+
# Bun
|
|
45
|
+
bun.lockb
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
FROM oven/bun:1 AS base
|
|
2
|
+
|
|
3
|
+
# Install dependencies only when needed
|
|
4
|
+
FROM base AS deps
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Copy package files
|
|
8
|
+
COPY package.json bun.lockb* ./
|
|
9
|
+
|
|
10
|
+
# Install dependencies
|
|
11
|
+
RUN bun install --frozen-lockfile
|
|
12
|
+
|
|
13
|
+
# Rebuild the source code only when needed
|
|
14
|
+
FROM base AS builder
|
|
15
|
+
WORKDIR /app
|
|
16
|
+
|
|
17
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
18
|
+
COPY . .
|
|
19
|
+
|
|
20
|
+
# Build the application
|
|
21
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
22
|
+
RUN bun run build
|
|
23
|
+
|
|
24
|
+
# Production image
|
|
25
|
+
FROM base AS runner
|
|
26
|
+
WORKDIR /app
|
|
27
|
+
|
|
28
|
+
ENV NODE_ENV=production
|
|
29
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
30
|
+
|
|
31
|
+
RUN useradd --system --uid 1001 nextjs
|
|
32
|
+
|
|
33
|
+
COPY --from=builder /app/public ./public
|
|
34
|
+
COPY --from=builder --chown=nextjs:bun /app/.next/standalone ./
|
|
35
|
+
COPY --from=builder --chown=nextjs:bun /app/.next/static ./.next/static
|
|
36
|
+
|
|
37
|
+
USER nextjs
|
|
38
|
+
|
|
39
|
+
EXPOSE {{ cookiecutter.frontend_port }}
|
|
40
|
+
|
|
41
|
+
ENV PORT={{ cookiecutter.frontend_port }}
|
|
42
|
+
ENV HOSTNAME="0.0.0.0"
|
|
43
|
+
|
|
44
|
+
CMD ["bun", "server.js"]
|