fastapi-fullstack 0.1.12__tar.gz → 0.1.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/PKG-INFO +4 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/README.md +3 -1
- fastapi_fullstack-0.1.14/fastapi_gen/__init__.py +8 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/fastapi_gen/config.py +77 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/fastapi_gen/generator.py +34 -14
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/fastapi_gen/prompts.py +126 -31
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/pyproject.toml +7 -1
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/hooks/post_gen_project.py +55 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/admin.py +1 -1
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/langchain_assistant.py +4 -3
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/oauth.py +3 -7
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/commands/cleanup.py +2 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/commands/seed.py +7 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/config.py +12 -7
- fastapi_fullstack-0.1.14/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +14 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/session.py +10 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/webhook.py +1 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/main.py +8 -2
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/base.py +6 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/session.py +4 -4
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/conversation.py +9 -9
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/session.py +6 -6
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/webhook.py +7 -7
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docker-compose.dev.yml +6 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docker-compose.prod.yml +39 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/.env.example +5 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/lib/constants.ts +1 -1
- fastapi_fullstack-0.1.12/fastapi_gen/__init__.py +0 -3
- fastapi_fullstack-0.1.12/template/{{cookiecutter.project_slug}}/backend/app/db/__init__.py +0 -7
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/.gitignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/LICENSE +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/fastapi_gen/cli.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/VARIABLES.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/cookiecutter.json +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/.env.prod.example +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/.gitignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/.gitlab-ci.yml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/AGENTS.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/CLAUDE.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/Makefile +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/README.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/.dockerignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/.env.example +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/.pre-commit-config.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/Dockerfile +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/alembic/env.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/alembic/script.py.mako +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/alembic/versions/.gitkeep +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/alembic.ini +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/assistant.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/crewai_assistant.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/langgraph_assistant.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/prompts.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/agents/tools/datetime_tool.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/deps.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/exception_handlers.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/router.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/agent.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/auth.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/conversations.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/health.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/items.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/sessions.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/users.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/webhooks.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/routes/v1/ws.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/api/versioning.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/clients/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/clients/redis.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/commands/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/commands/example.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/cache.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/csrf.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/exceptions.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/logfire_setup.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/middleware.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/oauth.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/rate_limit.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/sanitize.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/core/security.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/base.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/conversation.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/item.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/models/user.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/db/session.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/pipelines/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/pipelines/base.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/conversation.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/item.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/user.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/repositories/webhook.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/base.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/conversation.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/item.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/session.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/token.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/user.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/schemas/webhook.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/item.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/services/user.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/arq_app.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/celery_app.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/taskiq_app.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/examples.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/schedules.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/app/worker/tasks/taskiq_examples.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/cli/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/cli/commands.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/pyproject.toml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/scripts/.gitkeep +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/__init__.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_auth.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_exceptions.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_health.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_items.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_metrics.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/api/test_users.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/conftest.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_admin.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_agents.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_clients.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_commands.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_core.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_pipelines.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_repositories.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_security.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_services.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/backend/tests/test_worker.py +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docker-compose.frontend.yml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docker-compose.yml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docs/adding_features.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docs/architecture.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docs/patterns.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/docs/testing.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/.dockerignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/.gitignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/.prettierignore +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/.prettierrc +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/Dockerfile +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/README.md +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.setup.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/e2e/auth.spec.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/e2e/chat.spec.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/e2e/home.spec.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/instrumentation.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/messages/en.json +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/messages/pl.json +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/next.config.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/package.json +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/playwright.config.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/layout.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/login/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(auth)/register/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/chat/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/dashboard/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/layout.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/(dashboard)/profile/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/auth/callback/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/layout.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/[locale]/page.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/login/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/logout/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/me/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/oauth-callback/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/refresh/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/auth/register/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/messages/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/[id]/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/conversations/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/api/health/route.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/globals.css +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/layout.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/app/providers.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/login-form.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/auth/register-form.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-container.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/chat-input.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/conversation-sidebar.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/copy-button.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/local-conversation-sidebar.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/markdown-content.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-item.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/message-list.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/chat/tool-call-card.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/google-icon.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/icons/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/language-switcher.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/header.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/layout/sidebar.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-provider.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/theme/theme-toggle.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/badge.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.test.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/button.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/card.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/input.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/label.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/components/ui/sheet.tsx +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-auth.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-chat.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-conversations.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-local-chat.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/hooks/use-websocket.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/i18n.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/lib/api-client.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/lib/server-api.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.test.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/lib/utils.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/middleware.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.test.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/auth-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-sidebar-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/chat-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/conversation-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/local-chat-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/sidebar-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/stores/theme-store.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/types/api.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/types/auth.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/types/chat.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/types/conversation.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/src/types/index.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/tsconfig.json +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/configmap.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/deployment.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/ingress.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/kustomization.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/namespace.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/secret.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/kubernetes/service.yaml +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/nginx/nginx.conf +0 -0
- {fastapi_fullstack-0.1.12 → fastapi_fullstack-0.1.14}/template/{{cookiecutter.project_slug}}/nginx/ssl/.gitkeep +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-fullstack
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.14
|
|
4
4
|
Summary: Full-stack FastAPI + Next.js template generator with PydanticAI/LangChain agents, WebSocket streaming, 20+ enterprise integrations, and Logfire/LangSmith observability. Ship AI apps fast. CLI tool to generate production-ready FastAPI + Next.js projects with AI agents, auth, and observability.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template
|
|
6
6
|
Project-URL: Documentation, https://github.com/vstorm-co/full-stack-fastapi-nextjs-llm-template#readme
|
|
@@ -199,8 +199,10 @@ make docker-db
|
|
|
199
199
|
|
|
200
200
|
#### 3. Create and apply database migrations
|
|
201
201
|
|
|
202
|
+
> ⚠️ **Important:** Both commands are required! `db-migrate` creates the migration file, `db-upgrade` applies it to the database.
|
|
203
|
+
|
|
202
204
|
```bash
|
|
203
|
-
# Create initial migration (first time
|
|
205
|
+
# Create initial migration (REQUIRED first time)
|
|
204
206
|
make db-migrate
|
|
205
207
|
# Enter message: "Initial migration"
|
|
206
208
|
|
|
@@ -163,8 +163,10 @@ make docker-db
|
|
|
163
163
|
|
|
164
164
|
#### 3. Create and apply database migrations
|
|
165
165
|
|
|
166
|
+
> ⚠️ **Important:** Both commands are required! `db-migrate` creates the migration file, `db-upgrade` applies it to the database.
|
|
167
|
+
|
|
166
168
|
```bash
|
|
167
|
-
# Create initial migration (first time
|
|
169
|
+
# Create initial migration (REQUIRED first time)
|
|
168
170
|
make db-migrate
|
|
169
171
|
# Enter message: "Initial migration"
|
|
170
172
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""FastAPI Project Generator with Logfire observability."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("fastapi-fullstack")
|
|
7
|
+
except PackageNotFoundError:
|
|
8
|
+
__version__ = "0.0.0" # Development/editable install fallback
|
|
@@ -283,6 +283,83 @@ class ProjectConfig(BaseModel):
|
|
|
283
283
|
and not self.enable_redis
|
|
284
284
|
):
|
|
285
285
|
raise ValueError("Rate limiting with Redis storage requires Redis to be enabled")
|
|
286
|
+
|
|
287
|
+
# WebSocket JWT auth requires main JWT auth
|
|
288
|
+
if self.websocket_auth == WebSocketAuthType.JWT and self.auth not in (
|
|
289
|
+
AuthType.JWT,
|
|
290
|
+
AuthType.BOTH,
|
|
291
|
+
):
|
|
292
|
+
raise ValueError("WebSocket JWT authentication requires JWT auth to be enabled")
|
|
293
|
+
|
|
294
|
+
# WebSocket API key auth requires main API key auth
|
|
295
|
+
if self.websocket_auth == WebSocketAuthType.API_KEY and self.auth not in (
|
|
296
|
+
AuthType.API_KEY,
|
|
297
|
+
AuthType.BOTH,
|
|
298
|
+
):
|
|
299
|
+
raise ValueError("WebSocket API key authentication requires API key auth to be enabled")
|
|
300
|
+
|
|
301
|
+
# Admin panel authentication requires JWT (for User model and security functions)
|
|
302
|
+
if (
|
|
303
|
+
self.enable_admin_panel
|
|
304
|
+
and self.admin_require_auth
|
|
305
|
+
and self.auth not in (AuthType.JWT, AuthType.BOTH)
|
|
306
|
+
):
|
|
307
|
+
raise ValueError(
|
|
308
|
+
"Admin panel authentication requires JWT auth to be enabled. "
|
|
309
|
+
"Either enable JWT auth or set admin_require_auth=False"
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# Conversation persistence requires AI agent
|
|
313
|
+
if self.enable_conversation_persistence and not self.enable_ai_agent:
|
|
314
|
+
raise ValueError("Conversation persistence requires AI agent to be enabled")
|
|
315
|
+
|
|
316
|
+
# Admin panel requires SQLAlchemy (SQLAdmin doesn't fully support SQLModel)
|
|
317
|
+
if self.enable_admin_panel and self.orm_type == OrmType.SQLMODEL:
|
|
318
|
+
raise ValueError(
|
|
319
|
+
"Admin panel (SQLAdmin) requires SQLAlchemy ORM. "
|
|
320
|
+
"SQLModel is not fully supported. Use orm_type=sqlalchemy or disable admin panel."
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# Session management requires JWT auth
|
|
324
|
+
if self.enable_session_management and self.auth not in (AuthType.JWT, AuthType.BOTH):
|
|
325
|
+
raise ValueError("Session management requires JWT auth to be enabled")
|
|
326
|
+
|
|
327
|
+
# Webhooks require a database
|
|
328
|
+
if self.enable_webhooks and self.database == DatabaseType.NONE:
|
|
329
|
+
raise ValueError(
|
|
330
|
+
"Webhooks require a database to store subscriptions and delivery history"
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
# Background task queues require Redis
|
|
334
|
+
if (
|
|
335
|
+
self.background_tasks
|
|
336
|
+
in (
|
|
337
|
+
BackgroundTaskType.CELERY,
|
|
338
|
+
BackgroundTaskType.TASKIQ,
|
|
339
|
+
BackgroundTaskType.ARQ,
|
|
340
|
+
)
|
|
341
|
+
and not self.enable_redis
|
|
342
|
+
):
|
|
343
|
+
raise ValueError(
|
|
344
|
+
f"{self.background_tasks.value.title()} requires Redis to be enabled. "
|
|
345
|
+
"All task queue systems use Redis as broker/backend."
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
# Logfire feature-specific validations (only when logfire is enabled)
|
|
349
|
+
if self.enable_logfire:
|
|
350
|
+
if self.logfire_features.database and self.database == DatabaseType.NONE:
|
|
351
|
+
raise ValueError(
|
|
352
|
+
"Logfire database instrumentation requires a database to be enabled"
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
if self.logfire_features.redis and not self.enable_redis:
|
|
356
|
+
raise ValueError("Logfire Redis instrumentation requires Redis to be enabled")
|
|
357
|
+
|
|
358
|
+
if self.logfire_features.celery and self.background_tasks != BackgroundTaskType.CELERY:
|
|
359
|
+
raise ValueError(
|
|
360
|
+
"Logfire Celery instrumentation requires Celery as background task system"
|
|
361
|
+
)
|
|
362
|
+
|
|
286
363
|
return self
|
|
287
364
|
|
|
288
365
|
def to_cookiecutter_context(self) -> dict[str, Any]:
|
|
@@ -12,31 +12,31 @@ from .config import DatabaseType, FrontendType, ProjectConfig
|
|
|
12
12
|
console = Console()
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def _get_database_setup_commands(database: DatabaseType) -> list[str]:
|
|
15
|
+
def _get_database_setup_commands(database: DatabaseType) -> list[tuple[str, str]]:
|
|
16
16
|
"""Get database-specific setup commands for post-generation messages.
|
|
17
17
|
|
|
18
18
|
Args:
|
|
19
19
|
database: The database type selected by the user
|
|
20
20
|
|
|
21
21
|
Returns:
|
|
22
|
-
List of command
|
|
22
|
+
List of (command, description) tuples to display
|
|
23
23
|
"""
|
|
24
24
|
if database == DatabaseType.SQLITE:
|
|
25
25
|
return [
|
|
26
|
-
"# SQLite database will be created automatically
|
|
27
|
-
"make db-migrate
|
|
28
|
-
"make db-upgrade
|
|
26
|
+
("# SQLite database will be created automatically", ""),
|
|
27
|
+
("make db-migrate", "Create initial migration"),
|
|
28
|
+
("make db-upgrade", "Apply migrations"),
|
|
29
29
|
]
|
|
30
30
|
elif database == DatabaseType.MONGODB:
|
|
31
31
|
return [
|
|
32
|
-
"make docker-mongo
|
|
33
|
-
"# Or configure MongoDB Atlas connection in .env",
|
|
32
|
+
("make docker-mongo", "Start MongoDB container"),
|
|
33
|
+
("# Or configure MongoDB Atlas connection in .env", ""),
|
|
34
34
|
]
|
|
35
35
|
else: # PostgreSQL
|
|
36
36
|
return [
|
|
37
|
-
"make docker-db
|
|
38
|
-
"make db-migrate
|
|
39
|
-
"make db-upgrade
|
|
37
|
+
("make docker-db", "Start PostgreSQL container"),
|
|
38
|
+
("make db-migrate", "Create initial migration"),
|
|
39
|
+
("make db-upgrade", "Apply migrations"),
|
|
40
40
|
]
|
|
41
41
|
|
|
42
42
|
|
|
@@ -153,8 +153,18 @@ def post_generation_tasks(project_path: Path, config: ProjectConfig) -> None:
|
|
|
153
153
|
if config.database.value != "none":
|
|
154
154
|
console.print()
|
|
155
155
|
console.print(f"[bold]{step}. Database setup:[/]")
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
db_commands = _get_database_setup_commands(config.database)
|
|
157
|
+
for cmd, desc in db_commands:
|
|
158
|
+
if desc:
|
|
159
|
+
console.print(f" {cmd:22}# {desc}")
|
|
160
|
+
else:
|
|
161
|
+
console.print(f" {cmd}")
|
|
162
|
+
if config.database != DatabaseType.MONGODB:
|
|
163
|
+
console.print()
|
|
164
|
+
console.print(
|
|
165
|
+
" [dim]⚠️ Run all commands in order:[/] "
|
|
166
|
+
"[dim]db-migrate creates the migration, db-upgrade applies it[/]"
|
|
167
|
+
)
|
|
158
168
|
step += 1
|
|
159
169
|
console.print()
|
|
160
170
|
console.print(f"[bold]{step}. Run backend:[/]")
|
|
@@ -184,8 +194,18 @@ def post_generation_tasks(project_path: Path, config: ProjectConfig) -> None:
|
|
|
184
194
|
if config.database.value != "none":
|
|
185
195
|
console.print()
|
|
186
196
|
console.print(f"[bold]{step}. Database setup:[/]")
|
|
187
|
-
|
|
188
|
-
|
|
197
|
+
db_commands = _get_database_setup_commands(config.database)
|
|
198
|
+
for cmd, desc in db_commands:
|
|
199
|
+
if desc:
|
|
200
|
+
console.print(f" {cmd:22}# {desc}")
|
|
201
|
+
else:
|
|
202
|
+
console.print(f" {cmd}")
|
|
203
|
+
if config.database != DatabaseType.MONGODB:
|
|
204
|
+
console.print()
|
|
205
|
+
console.print(
|
|
206
|
+
" [dim]⚠️ Run all commands in order:[/] "
|
|
207
|
+
"[dim]db-migrate creates the migration, db-upgrade applies it[/]"
|
|
208
|
+
)
|
|
189
209
|
step += 1
|
|
190
210
|
console.print()
|
|
191
211
|
console.print(f"[bold]{step}. Run server:[/]")
|
|
@@ -157,11 +157,11 @@ def prompt_orm_type() -> OrmType:
|
|
|
157
157
|
"""Prompt for ORM library selection."""
|
|
158
158
|
choices = [
|
|
159
159
|
questionary.Choice(
|
|
160
|
-
"SQLAlchemy
|
|
160
|
+
"SQLAlchemy — full control, supports admin panel",
|
|
161
161
|
value=OrmType.SQLALCHEMY,
|
|
162
162
|
),
|
|
163
163
|
questionary.Choice(
|
|
164
|
-
"SQLModel
|
|
164
|
+
"SQLModel — less boilerplate, no admin panel support",
|
|
165
165
|
value=OrmType.SQLMODEL,
|
|
166
166
|
),
|
|
167
167
|
]
|
|
@@ -289,38 +289,120 @@ def prompt_background_tasks() -> BackgroundTaskType:
|
|
|
289
289
|
)
|
|
290
290
|
|
|
291
291
|
|
|
292
|
-
def prompt_integrations(
|
|
293
|
-
|
|
292
|
+
def prompt_integrations(
|
|
293
|
+
database: DatabaseType,
|
|
294
|
+
orm_type: OrmType,
|
|
295
|
+
) -> dict[str, bool]:
|
|
296
|
+
"""Prompt for optional integrations.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
database: Selected database type (affects which options are shown).
|
|
300
|
+
orm_type: Selected ORM type (SQLModel doesn't support admin panel).
|
|
301
|
+
"""
|
|
294
302
|
console.print()
|
|
295
303
|
console.print("[bold cyan]Optional Integrations[/]")
|
|
296
304
|
console.print()
|
|
297
305
|
|
|
306
|
+
# Build choices dynamically based on context
|
|
307
|
+
choices: list[questionary.Choice] = [
|
|
308
|
+
questionary.Choice(
|
|
309
|
+
"Redis — required for caching, rate limiting (Redis), task queues",
|
|
310
|
+
value="redis",
|
|
311
|
+
),
|
|
312
|
+
questionary.Choice(
|
|
313
|
+
"Caching (fastapi-cache2) — requires Redis",
|
|
314
|
+
value="caching",
|
|
315
|
+
),
|
|
316
|
+
questionary.Choice(
|
|
317
|
+
"Rate limiting (slowapi) — optional Redis storage",
|
|
318
|
+
value="rate_limiting",
|
|
319
|
+
),
|
|
320
|
+
questionary.Choice(
|
|
321
|
+
"Pagination (fastapi-pagination)",
|
|
322
|
+
value="pagination",
|
|
323
|
+
checked=True,
|
|
324
|
+
),
|
|
325
|
+
questionary.Choice(
|
|
326
|
+
"Sentry — error tracking & monitoring",
|
|
327
|
+
value="sentry",
|
|
328
|
+
),
|
|
329
|
+
questionary.Choice(
|
|
330
|
+
"Prometheus — metrics endpoint for monitoring",
|
|
331
|
+
value="prometheus",
|
|
332
|
+
),
|
|
333
|
+
]
|
|
334
|
+
|
|
335
|
+
# Admin Panel only available with SQLAlchemy (not SQLModel) and SQL database
|
|
336
|
+
if (
|
|
337
|
+
database in (DatabaseType.POSTGRESQL, DatabaseType.SQLITE)
|
|
338
|
+
and orm_type == OrmType.SQLALCHEMY
|
|
339
|
+
):
|
|
340
|
+
choices.append(
|
|
341
|
+
questionary.Choice(
|
|
342
|
+
"Admin Panel (SQLAdmin) — web UI for database management",
|
|
343
|
+
value="admin_panel",
|
|
344
|
+
)
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
choices.extend(
|
|
348
|
+
[
|
|
349
|
+
questionary.Choice(
|
|
350
|
+
"WebSockets — real-time bidirectional communication",
|
|
351
|
+
value="websockets",
|
|
352
|
+
),
|
|
353
|
+
questionary.Choice(
|
|
354
|
+
"File Storage (S3/MinIO) — file upload/download support",
|
|
355
|
+
value="file_storage",
|
|
356
|
+
),
|
|
357
|
+
questionary.Choice(
|
|
358
|
+
"AI Agent (PydanticAI/LangGraph/CrewAI) — LLM-powered assistant",
|
|
359
|
+
value="ai_agent",
|
|
360
|
+
checked=True,
|
|
361
|
+
),
|
|
362
|
+
]
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
# Webhooks require database
|
|
366
|
+
if database != DatabaseType.NONE:
|
|
367
|
+
choices.append(
|
|
368
|
+
questionary.Choice(
|
|
369
|
+
"Webhooks — outbound event notifications",
|
|
370
|
+
value="webhooks",
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
choices.extend(
|
|
375
|
+
[
|
|
376
|
+
questionary.Choice(
|
|
377
|
+
"Example CRUD (Item model) — sample API endpoints",
|
|
378
|
+
value="example_crud",
|
|
379
|
+
checked=True,
|
|
380
|
+
),
|
|
381
|
+
questionary.Choice(
|
|
382
|
+
"CORS middleware — cross-origin request support",
|
|
383
|
+
value="cors",
|
|
384
|
+
checked=True,
|
|
385
|
+
),
|
|
386
|
+
questionary.Choice(
|
|
387
|
+
"orjson — faster JSON serialization",
|
|
388
|
+
value="orjson",
|
|
389
|
+
checked=True,
|
|
390
|
+
),
|
|
391
|
+
]
|
|
392
|
+
)
|
|
393
|
+
|
|
298
394
|
features = _check_cancelled(
|
|
299
395
|
questionary.checkbox(
|
|
300
396
|
"Select additional features:",
|
|
301
|
-
choices=
|
|
302
|
-
questionary.Choice("Redis (caching/sessions)", value="redis"),
|
|
303
|
-
questionary.Choice("Caching (fastapi-cache2)", value="caching"),
|
|
304
|
-
questionary.Choice("Rate limiting (slowapi)", value="rate_limiting"),
|
|
305
|
-
questionary.Choice(
|
|
306
|
-
"Pagination (fastapi-pagination)", value="pagination", checked=True
|
|
307
|
-
),
|
|
308
|
-
questionary.Choice("Sentry (error tracking)", value="sentry"),
|
|
309
|
-
questionary.Choice("Prometheus (metrics)", value="prometheus"),
|
|
310
|
-
questionary.Choice("Admin Panel (SQLAdmin)", value="admin_panel"),
|
|
311
|
-
questionary.Choice("WebSockets", value="websockets"),
|
|
312
|
-
questionary.Choice("File Storage (S3/MinIO)", value="file_storage"),
|
|
313
|
-
questionary.Choice(
|
|
314
|
-
"AI Agent (PydanticAI/LangGraph/CrewAI)", value="ai_agent", checked=True
|
|
315
|
-
),
|
|
316
|
-
questionary.Choice("Webhooks (outbound events)", value="webhooks"),
|
|
317
|
-
questionary.Choice("Example CRUD (Item model)", value="example_crud", checked=True),
|
|
318
|
-
questionary.Choice("CORS middleware", value="cors", checked=True),
|
|
319
|
-
questionary.Choice("orjson (faster JSON)", value="orjson", checked=True),
|
|
320
|
-
],
|
|
397
|
+
choices=choices,
|
|
321
398
|
).ask()
|
|
322
399
|
)
|
|
323
400
|
|
|
401
|
+
# Auto-enable Redis for caching (show info message)
|
|
402
|
+
if "caching" in features and "redis" not in features:
|
|
403
|
+
console.print("[yellow]ℹ Caching requires Redis — auto-enabled[/]")
|
|
404
|
+
features.append("redis")
|
|
405
|
+
|
|
324
406
|
return {
|
|
325
407
|
"enable_redis": "redis" in features,
|
|
326
408
|
"enable_caching": "caching" in features,
|
|
@@ -582,18 +664,31 @@ def prompt_llm_provider(ai_framework: AIFrameworkType) -> LLMProviderType:
|
|
|
582
664
|
)
|
|
583
665
|
|
|
584
666
|
|
|
585
|
-
def prompt_websocket_auth() -> WebSocketAuthType:
|
|
586
|
-
"""Prompt for WebSocket authentication method for AI Agent.
|
|
667
|
+
def prompt_websocket_auth(auth: AuthType) -> WebSocketAuthType:
|
|
668
|
+
"""Prompt for WebSocket authentication method for AI Agent.
|
|
669
|
+
|
|
670
|
+
Args:
|
|
671
|
+
auth: The main auth type. JWT WebSocket auth is only available
|
|
672
|
+
if JWT is enabled (JWT or BOTH).
|
|
673
|
+
"""
|
|
587
674
|
console.print()
|
|
588
675
|
console.print("[bold cyan]AI Agent WebSocket Authentication[/]")
|
|
589
676
|
console.print()
|
|
590
677
|
|
|
591
678
|
choices = [
|
|
592
679
|
questionary.Choice("None (public access)", value=WebSocketAuthType.NONE),
|
|
593
|
-
questionary.Choice("JWT token required", value=WebSocketAuthType.JWT),
|
|
594
|
-
questionary.Choice("API Key required (query param)", value=WebSocketAuthType.API_KEY),
|
|
595
680
|
]
|
|
596
681
|
|
|
682
|
+
# JWT WebSocket auth only available if main auth uses JWT
|
|
683
|
+
if auth in (AuthType.JWT, AuthType.BOTH):
|
|
684
|
+
choices.append(questionary.Choice("JWT token required", value=WebSocketAuthType.JWT))
|
|
685
|
+
|
|
686
|
+
# API Key WebSocket auth available if main auth uses API keys
|
|
687
|
+
if auth in (AuthType.API_KEY, AuthType.BOTH):
|
|
688
|
+
choices.append(
|
|
689
|
+
questionary.Choice("API Key required (query param)", value=WebSocketAuthType.API_KEY)
|
|
690
|
+
)
|
|
691
|
+
|
|
597
692
|
return cast(
|
|
598
693
|
WebSocketAuthType,
|
|
599
694
|
_check_cancelled(
|
|
@@ -744,8 +839,8 @@ def run_interactive_prompts() -> ProjectConfig:
|
|
|
744
839
|
# Background tasks
|
|
745
840
|
background_tasks = prompt_background_tasks()
|
|
746
841
|
|
|
747
|
-
# Integrations
|
|
748
|
-
integrations = prompt_integrations()
|
|
842
|
+
# Integrations (pass context for dynamic option filtering)
|
|
843
|
+
integrations = prompt_integrations(database=database, orm_type=orm_type)
|
|
749
844
|
|
|
750
845
|
# Dev tools
|
|
751
846
|
dev_tools = prompt_dev_tools()
|
|
@@ -780,7 +875,7 @@ def run_interactive_prompts() -> ProjectConfig:
|
|
|
780
875
|
if integrations.get("enable_ai_agent"):
|
|
781
876
|
ai_framework = prompt_ai_framework()
|
|
782
877
|
llm_provider = prompt_llm_provider(ai_framework)
|
|
783
|
-
websocket_auth = prompt_websocket_auth()
|
|
878
|
+
websocket_auth = prompt_websocket_auth(auth=auth)
|
|
784
879
|
# Only offer persistence if database is enabled
|
|
785
880
|
if database != DatabaseType.NONE:
|
|
786
881
|
enable_conversation_persistence = _check_cancelled(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fastapi-fullstack"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.14"
|
|
4
4
|
description = "Full-stack FastAPI + Next.js template generator with PydanticAI/LangChain agents, WebSocket streaming, 20+ enterprise integrations, and Logfire/LangSmith observability. Ship AI apps fast. CLI tool to generate production-ready FastAPI + Next.js projects with AI agents, auth, and observability."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -165,3 +165,9 @@ exclude_lines = [
|
|
|
165
165
|
"if TYPE_CHECKING:",
|
|
166
166
|
"raise NotImplementedError",
|
|
167
167
|
]
|
|
168
|
+
|
|
169
|
+
[dependency-groups]
|
|
170
|
+
dev = [
|
|
171
|
+
"mypy>=1.19.1",
|
|
172
|
+
"pytest-cov>=7.0.0",
|
|
173
|
+
]
|
|
@@ -16,10 +16,14 @@ use_database = "{{ cookiecutter.use_database }}" == "True"
|
|
|
16
16
|
use_postgresql = "{{ cookiecutter.use_postgresql }}" == "True"
|
|
17
17
|
use_sqlite = "{{ cookiecutter.use_sqlite }}" == "True"
|
|
18
18
|
use_mongodb = "{{ cookiecutter.use_mongodb }}" == "True"
|
|
19
|
+
use_sqlalchemy = "{{ cookiecutter.use_sqlalchemy }}" == "True"
|
|
20
|
+
use_sqlmodel = "{{ cookiecutter.use_sqlmodel }}" == "True"
|
|
19
21
|
include_example_crud = "{{ cookiecutter.include_example_crud }}" == "True"
|
|
20
22
|
enable_ai_agent = "{{ cookiecutter.enable_ai_agent }}" == "True"
|
|
21
23
|
use_pydantic_ai = "{{ cookiecutter.use_pydantic_ai }}" == "True"
|
|
22
24
|
use_langchain = "{{ cookiecutter.use_langchain }}" == "True"
|
|
25
|
+
use_langgraph = "{{ cookiecutter.use_langgraph }}" == "True"
|
|
26
|
+
use_crewai = "{{ cookiecutter.use_crewai }}" == "True"
|
|
23
27
|
enable_admin_panel = "{{ cookiecutter.enable_admin_panel }}" == "True"
|
|
24
28
|
enable_websockets = "{{ cookiecutter.enable_websockets }}" == "True"
|
|
25
29
|
enable_redis = "{{ cookiecutter.enable_redis }}" == "True"
|
|
@@ -30,6 +34,7 @@ enable_conversation_persistence = "{{ cookiecutter.enable_conversation_persisten
|
|
|
30
34
|
enable_webhooks = "{{ cookiecutter.enable_webhooks }}" == "True"
|
|
31
35
|
enable_oauth = "{{ cookiecutter.enable_oauth }}" == "True"
|
|
32
36
|
use_jwt = "{{ cookiecutter.use_jwt }}" == "True"
|
|
37
|
+
use_api_key = "{{ cookiecutter.use_api_key }}" == "True"
|
|
33
38
|
use_celery = "{{ cookiecutter.use_celery }}" == "True"
|
|
34
39
|
use_taskiq = "{{ cookiecutter.use_taskiq }}" == "True"
|
|
35
40
|
use_arq = "{{ cookiecutter.use_arq }}" == "True"
|
|
@@ -37,6 +42,7 @@ use_github_actions = "{{ cookiecutter.use_github_actions }}" == "True"
|
|
|
37
42
|
use_gitlab_ci = "{{ cookiecutter.use_gitlab_ci }}" == "True"
|
|
38
43
|
enable_kubernetes = "{{ cookiecutter.enable_kubernetes }}" == "True"
|
|
39
44
|
use_nginx = "{{ cookiecutter.use_nginx }}" == "True"
|
|
45
|
+
enable_logfire = "{{ cookiecutter.enable_logfire }}" == "True"
|
|
40
46
|
|
|
41
47
|
|
|
42
48
|
def remove_file(path: str) -> None:
|
|
@@ -46,6 +52,23 @@ def remove_file(path: str) -> None:
|
|
|
46
52
|
print(f" Removed: {os.path.relpath(path)}")
|
|
47
53
|
|
|
48
54
|
|
|
55
|
+
def is_stub_file(filepath: str) -> bool:
|
|
56
|
+
"""Check if file only contains a docstring stub with no real code."""
|
|
57
|
+
if not os.path.exists(filepath):
|
|
58
|
+
return False
|
|
59
|
+
with open(filepath) as f:
|
|
60
|
+
content = f.read().strip()
|
|
61
|
+
# Empty file
|
|
62
|
+
if not content:
|
|
63
|
+
return True
|
|
64
|
+
# File only has docstring (triple-quoted string)
|
|
65
|
+
if content.startswith('"""') and content.endswith('"""'):
|
|
66
|
+
# Check if there's only one docstring and no code
|
|
67
|
+
inner = content[3:-3].strip()
|
|
68
|
+
return '"""' not in inner and "def " not in content and "class " not in content
|
|
69
|
+
return False
|
|
70
|
+
|
|
71
|
+
|
|
49
72
|
def remove_dir(path: str) -> None:
|
|
50
73
|
"""Remove a directory if it exists."""
|
|
51
74
|
if os.path.exists(path):
|
|
@@ -72,6 +95,10 @@ else:
|
|
|
72
95
|
remove_file(os.path.join(backend_app, "agents", "assistant.py"))
|
|
73
96
|
if not use_langchain:
|
|
74
97
|
remove_file(os.path.join(backend_app, "agents", "langchain_assistant.py"))
|
|
98
|
+
if not use_langgraph:
|
|
99
|
+
remove_file(os.path.join(backend_app, "agents", "langgraph_assistant.py"))
|
|
100
|
+
if not use_crewai:
|
|
101
|
+
remove_file(os.path.join(backend_app, "agents", "crewai_assistant.py"))
|
|
75
102
|
|
|
76
103
|
# --- Example CRUD files ---
|
|
77
104
|
if not include_example_crud or not use_database:
|
|
@@ -109,8 +136,8 @@ if not enable_session_management or not use_jwt:
|
|
|
109
136
|
if not enable_websockets:
|
|
110
137
|
remove_file(os.path.join(backend_app, "api", "routes", "v1", "ws.py"))
|
|
111
138
|
|
|
112
|
-
# --- Admin panel ---
|
|
113
|
-
if not enable_admin_panel or (not use_postgresql and not use_sqlite):
|
|
139
|
+
# --- Admin panel (requires SQLAlchemy, not SQLModel) ---
|
|
140
|
+
if not enable_admin_panel or (not use_postgresql and not use_sqlite) or not use_sqlalchemy:
|
|
114
141
|
remove_file(os.path.join(backend_app, "admin.py"))
|
|
115
142
|
|
|
116
143
|
# --- Redis/Cache files ---
|
|
@@ -129,6 +156,32 @@ if not enable_oauth:
|
|
|
129
156
|
remove_file(os.path.join(backend_app, "api", "routes", "v1", "oauth.py"))
|
|
130
157
|
remove_file(os.path.join(backend_app, "core", "oauth.py"))
|
|
131
158
|
|
|
159
|
+
# --- Security file (only when no auth at all) ---
|
|
160
|
+
if not use_jwt and not use_api_key:
|
|
161
|
+
remove_file(os.path.join(backend_app, "core", "security.py"))
|
|
162
|
+
|
|
163
|
+
# --- Auth/User files (when JWT is disabled) ---
|
|
164
|
+
if not use_jwt:
|
|
165
|
+
remove_file(os.path.join(backend_app, "api", "routes", "v1", "auth.py"))
|
|
166
|
+
remove_file(os.path.join(backend_app, "api", "routes", "v1", "users.py"))
|
|
167
|
+
remove_file(os.path.join(backend_app, "db", "models", "user.py"))
|
|
168
|
+
remove_file(os.path.join(backend_app, "repositories", "user.py"))
|
|
169
|
+
remove_file(os.path.join(backend_app, "services", "user.py"))
|
|
170
|
+
remove_file(os.path.join(backend_app, "schemas", "user.py"))
|
|
171
|
+
remove_file(os.path.join(backend_app, "schemas", "token.py"))
|
|
172
|
+
|
|
173
|
+
# --- Logfire setup file (when logfire is disabled) ---
|
|
174
|
+
if not enable_logfire:
|
|
175
|
+
remove_file(os.path.join(backend_app, "core", "logfire_setup.py"))
|
|
176
|
+
|
|
177
|
+
# --- Cleanup stub files (files with only docstring, no code) ---
|
|
178
|
+
core_dir = os.path.join(backend_app, "core")
|
|
179
|
+
for stub_candidate in ["security.py", "cache.py", "rate_limit.py", "oauth.py", "logfire_setup.py", "csrf.py"]:
|
|
180
|
+
filepath = os.path.join(core_dir, stub_candidate)
|
|
181
|
+
if is_stub_file(filepath):
|
|
182
|
+
remove_file(filepath)
|
|
183
|
+
print(f" Removed stub: {os.path.relpath(filepath)}")
|
|
184
|
+
|
|
132
185
|
# --- Worker/Background tasks ---
|
|
133
186
|
use_any_background_tasks = use_celery or use_taskiq or use_arq
|
|
134
187
|
if not use_any_background_tasks:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
{%- if cookiecutter.enable_admin_panel and cookiecutter.use_postgresql %}
|
|
1
|
+
{%- if cookiecutter.enable_admin_panel and (cookiecutter.use_postgresql or cookiecutter.use_sqlite) and cookiecutter.use_sqlalchemy %}
|
|
2
2
|
"""SQLAdmin configuration with automatic model discovery."""
|
|
3
3
|
|
|
4
4
|
from typing import Any, ClassVar
|
|
@@ -163,7 +163,7 @@ class LangChainAssistant:
|
|
|
163
163
|
|
|
164
164
|
return output, tool_events, agent_context
|
|
165
165
|
|
|
166
|
-
def stream(
|
|
166
|
+
async def stream(
|
|
167
167
|
self,
|
|
168
168
|
user_input: str,
|
|
169
169
|
history: list[dict[str, str]] | None = None,
|
|
@@ -186,11 +186,12 @@ class LangChainAssistant:
|
|
|
186
186
|
|
|
187
187
|
agent_context: AgentContext = context if context is not None else {}
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
async for event in self.agent.astream(
|
|
190
190
|
{"messages": messages},
|
|
191
191
|
stream_mode=["messages", "updates"],
|
|
192
192
|
config={"configurable": agent_context} if agent_context else None,
|
|
193
|
-
)
|
|
193
|
+
):
|
|
194
|
+
yield event
|
|
194
195
|
|
|
195
196
|
|
|
196
197
|
def get_agent() -> LangChainAssistant:
|
|
@@ -141,19 +141,15 @@ async def google_callback(request: Request, user_service: UserSvc):
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
@router.get("/google/callback")
|
|
144
|
-
def google_callback(request: Request, user_service: UserSvc):
|
|
144
|
+
async def google_callback(request: Request, user_service: UserSvc):
|
|
145
145
|
"""Handle Google OAuth2 callback.
|
|
146
146
|
|
|
147
147
|
Creates a new user if one doesn't exist with the Google email,
|
|
148
148
|
or returns tokens for existing user. Redirects to frontend with tokens.
|
|
149
149
|
"""
|
|
150
|
-
import asyncio
|
|
151
|
-
|
|
152
150
|
try:
|
|
153
|
-
#
|
|
154
|
-
|
|
155
|
-
token = loop.run_until_complete(oauth.google.authorize_access_token(request))
|
|
156
|
-
loop.close()
|
|
151
|
+
# OAuth token exchange is async
|
|
152
|
+
token = await oauth.google.authorize_access_token(request)
|
|
157
153
|
|
|
158
154
|
user_info = token.get("userinfo")
|
|
159
155
|
|
|
@@ -6,7 +6,7 @@ This command is useful for maintenance tasks.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import asyncio
|
|
9
|
-
from datetime import datetime, timedelta
|
|
9
|
+
from datetime import UTC, datetime, timedelta
|
|
10
10
|
|
|
11
11
|
import click
|
|
12
12
|
|
|
@@ -26,7 +26,7 @@ def cleanup(days: int, dry_run: bool, force: bool) -> None:
|
|
|
26
26
|
project cmd cleanup --days 30 --dry-run
|
|
27
27
|
project cmd cleanup --days 7 --force
|
|
28
28
|
"""
|
|
29
|
-
cutoff_date = datetime.
|
|
29
|
+
cutoff_date = datetime.now(UTC) - timedelta(days=days)
|
|
30
30
|
|
|
31
31
|
if dry_run:
|
|
32
32
|
info(f"[DRY RUN] Would delete records older than {cutoff_date}")
|
|
@@ -7,13 +7,16 @@ This command is useful for development and testing.
|
|
|
7
7
|
Uses random data generation - install faker for better data:
|
|
8
8
|
uv add faker --group dev
|
|
9
9
|
"""
|
|
10
|
-
|
|
10
|
+
{% if cookiecutter.use_postgresql %}
|
|
11
11
|
import asyncio
|
|
12
|
+
{% endif %}
|
|
12
13
|
import random
|
|
13
14
|
import string
|
|
14
15
|
|
|
15
16
|
import click
|
|
17
|
+
{% if cookiecutter.use_jwt or cookiecutter.include_example_crud %}
|
|
16
18
|
from sqlalchemy import delete, select
|
|
19
|
+
{% endif %}
|
|
17
20
|
|
|
18
21
|
from app.commands import command, info, success, warning
|
|
19
22
|
|
|
@@ -109,7 +112,9 @@ def seed(
|
|
|
109
112
|
{%- endif %}
|
|
110
113
|
return
|
|
111
114
|
|
|
112
|
-
{%- if cookiecutter.
|
|
115
|
+
{%- if not cookiecutter.use_jwt and not cookiecutter.include_example_crud %}
|
|
116
|
+
info("No entities configured to seed. Enable JWT users or example CRUD to use this command.")
|
|
117
|
+
{%- elif cookiecutter.use_postgresql %}
|
|
113
118
|
from app.db.session import async_session_maker
|
|
114
119
|
{%- if cookiecutter.use_jwt %}
|
|
115
120
|
from app.db.models.user import User
|