FastAPI-fastkit 1.3.0__py3-none-any.whl โ 1.4.1__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_fastkit/__init__.py +1 -1
- fastapi_fastkit/backend/inspection/__init__.py +26 -0
- fastapi_fastkit/backend/inspection/checks.py +349 -0
- fastapi_fastkit/backend/inspection/consistency.py +125 -0
- fastapi_fastkit/backend/inspection/context.py +71 -0
- fastapi_fastkit/backend/inspection/core.py +351 -0
- fastapi_fastkit/backend/inspection/docker.py +320 -0
- fastapi_fastkit/backend/inspection/freshness.py +145 -0
- fastapi_fastkit/backend/inspection/fsutils.py +139 -0
- fastapi_fastkit/backend/inspection/lint.py +103 -0
- fastapi_fastkit/backend/inspection/report.py +58 -0
- fastapi_fastkit/backend/inspection/smoke.py +381 -0
- fastapi_fastkit/backend/inspection/strategies.py +367 -0
- fastapi_fastkit/backend/inspector.py +18 -1400
- fastapi_fastkit/backend/interactive/__init__.py +6 -0
- fastapi_fastkit/backend/interactive/config_builder.py +45 -63
- fastapi_fastkit/backend/interactive/prompts.py +155 -6
- fastapi_fastkit/backend/interactive/selectors.py +18 -2
- fastapi_fastkit/backend/main.py +887 -99
- fastapi_fastkit/backend/package_managers/base.py +172 -0
- fastapi_fastkit/backend/package_managers/factory.py +5 -4
- fastapi_fastkit/backend/package_managers/pdm_manager.py +29 -82
- fastapi_fastkit/backend/package_managers/pip_manager.py +31 -85
- fastapi_fastkit/backend/package_managers/poetry_manager.py +70 -110
- fastapi_fastkit/backend/package_managers/uv_manager.py +43 -112
- fastapi_fastkit/backend/project_builder/__init__.py +8 -1
- fastapi_fastkit/backend/project_builder/config_generator.py +806 -450
- fastapi_fastkit/backend/project_builder/config_schema.py +384 -0
- fastapi_fastkit/backend/project_builder/dependency_collector.py +105 -66
- fastapi_fastkit/backend/project_builder/preset_layout.py +254 -28
- fastapi_fastkit/backend/scaffolder.py +578 -0
- fastapi_fastkit/backend/transducer.py +154 -22
- fastapi_fastkit/cli.py +434 -311
- fastapi_fastkit/core/settings.py +234 -45
- fastapi_fastkit/fastapi_project_template/README.md +26 -10
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/README.md-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/requirements.txt-tpl +39 -36
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/.env-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/.gitignore-tpl +33 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/README.md-tpl +210 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/alembic.ini-tpl +119 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/pyproject.toml-tpl +86 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/requirements.txt-tpl +23 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/README-tpl +1 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/env.py-tpl +51 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/script.py.mako-tpl +26 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/alembic/versions/0001_initial_auth_schema.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/deps.py-tpl +91 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/api/router.py-tpl +17 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/config.py-tpl +64 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/core/security.py-tpl +100 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/db/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/db/session.py-tpl +36 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/models.py-tpl +25 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/repository.py-tpl +41 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/router.py-tpl +82 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/schemas.py-tpl +14 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/auth/service.py-tpl +65 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/models.py-tpl +35 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/repository.py-tpl +33 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/router.py-tpl +71 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/schemas.py-tpl +29 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/domains/users/service.py-tpl +55 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/src/app/main.py-tpl +69 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/conftest.py-tpl +73 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_auth.py-tpl +201 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_health.py-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/tests/test_users.py-tpl +77 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/requirements.txt-tpl +39 -36
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/api/routes/items.py-tpl +3 -3
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/helper/pagination.py-tpl +8 -8
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/main.py-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/base.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-default/pyproject.toml-tpl +18 -19
- fastapi_fastkit/fastapi_project_template/fastapi-default/requirements.txt-tpl +37 -34
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/conftest.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-default/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/Dockerfile-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/README.md-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/pyproject.toml-tpl +21 -22
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/requirements.txt-tpl +41 -36
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/api/routes/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/crud/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/main.py-tpl +9 -1
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/src/schemas/items.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/conftest.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/pyproject.toml-tpl +13 -14
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/requirements.txt-tpl +36 -10
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/api/router.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/core/config.py-tpl +4 -4
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/db/memory.py-tpl +4 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/repository.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/router.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/domains/items/service.py-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/src/app/main.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/pyproject.toml-tpl +14 -15
- fastapi_fastkit/fastapi_project_template/fastapi-empty/requirements.txt-tpl +36 -10
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-empty/src/main.py-tpl +3 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-empty/tests/test_main.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/.env-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/.gitignore-tpl +31 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/README.md-tpl +193 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/pyproject.toml-tpl +76 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/requirements.txt-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/chat.sh-tpl +10 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/chat.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/deps.py-tpl +23 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/api/router.py-tpl +13 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/core/config.py-tpl +67 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/agent.py-tpl +136 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/client.py-tpl +30 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/llm/tools.py-tpl +131 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/main.py-tpl +53 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/base.py-tpl +27 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/memory/in_memory.py-tpl +32 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/schemas/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/src/app/schemas/chat.py-tpl +46 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/conftest.py-tpl +158 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_chat.py-tpl +160 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_health.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_memory.py-tpl +38 -0
- fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/tests/test_tools.py-tpl +37 -0
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/.env-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/README.md-tpl +2 -2
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/pyproject.toml-tpl +25 -26
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/requirements.txt-tpl +65 -40
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/setup.cfg-tpl +2 -3
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/api.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/routes/auth.py-tpl +13 -14
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/api/routes/items.py-tpl +3 -4
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/auth/dependencies.py-tpl +6 -7
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/core/config.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/main.py-tpl +4 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/{mcp โ mcp_server}/router.py-tpl +3 -5
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/schemas/items.py-tpl +6 -7
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/conftest.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_auth.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_items.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/tests/test_mcp.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/.env-tpl +2 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/Dockerfile-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/pyproject.toml-tpl +22 -23
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/requirements.txt-tpl +44 -41
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/env.py-tpl +1 -3
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/alembic/versions/bedcdc35b64a_first_alembic.py-tpl +5 -6
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/api.py-tpl +2 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/api/routes/items.py-tpl +2 -4
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/config.py-tpl +1 -2
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/core/db.py-tpl +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/crud/items.py-tpl +4 -6
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/main.py-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/src/schemas/items.py-tpl +4 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/conftest.py-tpl +1 -5
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/tests/test_items.py-tpl +0 -2
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/.env-tpl +1 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/.gitignore-tpl +30 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/pyproject.toml-tpl +3 -4
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/requirements.txt-tpl +26 -6
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/src/main.py-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/tests/conftest.py-tpl +0 -1
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/.env-tpl +7 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/.gitignore-tpl +35 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/Dockerfile-tpl +18 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/README.md-tpl +166 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/alembic.ini-tpl +44 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/pyproject.toml-tpl +82 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/requirements.txt-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/format.sh-tpl +5 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/lint.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/migrate.sh-tpl +7 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/run-server.sh-tpl +8 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/scripts/test.sh-tpl +6 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/README-tpl +9 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/env.py-tpl +72 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/script.py.mako-tpl +27 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/alembic/versions/0001_create_items_table.py-tpl +38 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/health.py-tpl +11 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/api/router.py-tpl +15 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/core/config.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/base.py-tpl +62 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/crud/pagination.py-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/base.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/db/session.py-tpl +50 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/crud.py-tpl +26 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/models.py-tpl +70 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/domains/items/router.py-tpl +69 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/src/app/main.py-tpl +43 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/template-config.yml-tpl +16 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/conftest.py-tpl +60 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_crud_base.py-tpl +43 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_health.py-tpl +12 -0
- fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/tests/test_items.py-tpl +110 -0
- fastapi_fastkit/fastapi_project_template/modules/api/routes/new_route.py-tpl +2 -2
- fastapi_fastkit/fragments/README.md +90 -0
- fastapi_fastkit/fragments/auth/fastapi_users.py.j2 +8 -0
- fastapi_fastkit/fragments/auth/jwt.py.j2 +44 -0
- fastapi_fastkit/fragments/auth/oauth2.py.j2 +105 -0
- fastapi_fastkit/fragments/auth/session.py.j2 +67 -0
- fastapi_fastkit/fragments/db/mongodb.py.j2 +19 -0
- fastapi_fastkit/fragments/db/redis.py.j2 +26 -0
- fastapi_fastkit/fragments/db/sqlalchemy.py.j2 +45 -0
- fastapi_fastkit/fragments/docker/docker_compose.j2 +84 -0
- fastapi_fastkit/fragments/docker/dockerfile.j2 +19 -0
- fastapi_fastkit/fragments/features/cache.py.j2 +26 -0
- fastapi_fastkit/fragments/features/pagination.py.j2 +31 -0
- fastapi_fastkit/fragments/features/tasks_celery.py.j2 +50 -0
- fastapi_fastkit/fragments/features/tasks_dramatiq.py.j2 +59 -0
- fastapi_fastkit/fragments/features/websocket.py.j2 +66 -0
- fastapi_fastkit/fragments/header.j2 +4 -0
- fastapi_fastkit/fragments/logging/structured.py.j2 +88 -0
- fastapi_fastkit/fragments/main/imports/async_tasks.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/caching.j2 +5 -0
- fastapi_fastkit/fragments/main/imports/fastapi_users.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/jwt.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/loguru.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/mongodb.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/oauth2.j2 +4 -0
- fastapi_fastkit/fragments/main/imports/opentelemetry.j2 +6 -0
- fastapi_fastkit/fragments/main/imports/pagination.j2 +3 -0
- fastapi_fastkit/fragments/main/imports/prometheus.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/rate_limiting.j2 +3 -0
- fastapi_fastkit/fragments/main/imports/session_auth.j2 +4 -0
- fastapi_fastkit/fragments/main/imports/sqlalchemy.j2 +2 -0
- fastapi_fastkit/fragments/main/imports/structured_logging.j2 +1 -0
- fastapi_fastkit/fragments/main/imports/websocket.j2 +1 -0
- fastapi_fastkit/fragments/main/lifespan/caching.j2 +7 -0
- fastapi_fastkit/fragments/main/lifespan/mongodb.j2 +2 -0
- fastapi_fastkit/fragments/main/lifespan/prometheus.j2 +2 -0
- fastapi_fastkit/fragments/main/lifespan/sqlalchemy.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/async_tasks.j2 +1 -0
- fastapi_fastkit/fragments/main/setup/caching.j2 +1 -0
- fastapi_fastkit/fragments/main/setup/cors.j2 +8 -0
- fastapi_fastkit/fragments/main/setup/oauth2.j2 +3 -0
- fastapi_fastkit/fragments/main/setup/opentelemetry.j2 +19 -0
- fastapi_fastkit/fragments/main/setup/pagination.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/rate_limiting.j2 +3 -0
- fastapi_fastkit/fragments/main/setup/session_auth.j2 +6 -0
- fastapi_fastkit/fragments/main/setup/structured_logging.j2 +2 -0
- fastapi_fastkit/fragments/main/setup/websocket.j2 +1 -0
- fastapi_fastkit/fragments/main.py.j2 +57 -0
- fastapi_fastkit/fragments/migrations/alembic_ini.j2 +42 -0
- fastapi_fastkit/fragments/migrations/env.py.j2 +76 -0
- fastapi_fastkit/fragments/migrations/initial_revision.py.j2 +27 -0
- fastapi_fastkit/fragments/migrations/migrate_sh.j2 +34 -0
- fastapi_fastkit/fragments/migrations/script.py.mako.j2 +26 -0
- fastapi_fastkit/fragments/tasks/celery_worker.py.j2 +49 -0
- fastapi_fastkit/fragments/tasks/dramatiq_worker.py.j2 +41 -0
- fastapi_fastkit/fragments/test/factories.py.j2 +68 -0
- fastapi_fastkit/fragments/test/pytest_ini.j2 +16 -0
- fastapi_fastkit/fragments/test/test_factories.py.j2 +27 -0
- fastapi_fastkit/fragments/test/test_main.py.j2 +46 -0
- fastapi_fastkit/fragments/tooling/devcontainer.j2 +26 -0
- fastapi_fastkit/fragments/tooling/github_actions.j2 +37 -0
- fastapi_fastkit/fragments/tooling/makefile.j2 +40 -0
- fastapi_fastkit/fragments/tooling/pre_commit.j2 +36 -0
- fastapi_fastkit/fragments/tooling/ruff_toml.j2 +16 -0
- fastapi_fastkit/utils/config_file.py +263 -0
- fastapi_fastkit/utils/main.py +38 -0
- {fastapi_fastkit-1.3.0.dist-info โ fastapi_fastkit-1.4.1.dist-info}/METADATA +49 -6
- fastapi_fastkit-1.4.1.dist-info/RECORD +484 -0
- {fastapi_fastkit-1.3.0.dist-info โ fastapi_fastkit-1.4.1.dist-info}/WHEEL +1 -1
- fastapi_fastkit/fastapi_project_template/fastapi-async-crud/setup.py-tpl +0 -25
- fastapi_fastkit/fastapi_project_template/fastapi-custom-response/setup.py-tpl +0 -27
- fastapi_fastkit/fastapi_project_template/fastapi-default/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-empty/setup.py-tpl +0 -22
- fastapi_fastkit/fastapi_project_template/fastapi-mcp/setup.py-tpl +0 -51
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/setup.py-tpl +0 -25
- fastapi_fastkit/fastapi_project_template/fastapi-single-module/setup.py-tpl +0 -17
- fastapi_fastkit-1.3.0.dist-info/RECORD +0 -287
- /fastapi_fastkit/fastapi_project_template/fastapi-mcp/src/{mcp โ mcp_server}/__init__.py-tpl +0 -0
- {fastapi_fastkit-1.3.0.dist-info โ fastapi_fastkit-1.4.1.dist-info}/entry_points.txt +0 -0
- {fastapi_fastkit-1.3.0.dist-info โ fastapi_fastkit-1.4.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# Project configuration file (de)serialization for non-interactive ``init``.
|
|
3
|
+
#
|
|
4
|
+
# ``fastkit init --interactive`` builds a plain configuration dict; this
|
|
5
|
+
# module lets that same dict travel through a file so a project can be
|
|
6
|
+
# reproduced without answering a single prompt (``--config``), and so an
|
|
7
|
+
# interactive session can be captured for later reuse (``--save-config``).
|
|
8
|
+
#
|
|
9
|
+
# Supported formats are picked from the file extension: JSON and TOML are
|
|
10
|
+
# always available (both ship with the stdlib on Python 3.12), YAML only
|
|
11
|
+
# when PyYAML happens to be installed โ fastkit deliberately does not add it
|
|
12
|
+
# as a runtime dependency.
|
|
13
|
+
#
|
|
14
|
+
# @author bnbong bbbong9@gmail.com
|
|
15
|
+
# --------------------------------------------------------------------------
|
|
16
|
+
import importlib
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
import tomllib
|
|
20
|
+
from typing import Any, Dict, List, Tuple
|
|
21
|
+
|
|
22
|
+
from fastapi_fastkit.backend.interactive.validators import (
|
|
23
|
+
validate_email_format,
|
|
24
|
+
validate_project_name,
|
|
25
|
+
)
|
|
26
|
+
from fastapi_fastkit.backend.project_builder.config_schema import (
|
|
27
|
+
ConfigSchemaError,
|
|
28
|
+
normalize_project_config,
|
|
29
|
+
validate_project_config_schema,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
JSON_EXTENSIONS: Tuple[str, ...] = (".json",)
|
|
33
|
+
TOML_EXTENSIONS: Tuple[str, ...] = (".toml",)
|
|
34
|
+
YAML_EXTENSIONS: Tuple[str, ...] = (".yaml", ".yml")
|
|
35
|
+
|
|
36
|
+
SUPPORTED_EXTENSIONS: Tuple[str, ...] = (
|
|
37
|
+
JSON_EXTENSIONS + TOML_EXTENSIONS + YAML_EXTENSIONS
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Keys the scaffolder needs; everything else in the file is passed through
|
|
41
|
+
# untouched so feature blocks stay forward-compatible.
|
|
42
|
+
REQUIRED_KEYS: Tuple[str, ...] = ("project_name", "author", "author_email")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ConfigFileError(Exception):
|
|
46
|
+
"""Raised when a project config file cannot be read, parsed or trusted."""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _yaml_module() -> Any:
|
|
50
|
+
"""Return the optional PyYAML module, or None when it isn't installed."""
|
|
51
|
+
try:
|
|
52
|
+
# Imported dynamically: PyYAML is optional, so a static import would
|
|
53
|
+
# make it look like a hard dependency to type checkers and readers.
|
|
54
|
+
return importlib.import_module("yaml")
|
|
55
|
+
except ImportError:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def load_project_config(path: str) -> Dict[str, Any]:
|
|
60
|
+
"""
|
|
61
|
+
Load a project configuration dict from a JSON / TOML / YAML file.
|
|
62
|
+
|
|
63
|
+
:param path: Path to the configuration file
|
|
64
|
+
:return: Configuration dictionary equivalent to the interactive builder's
|
|
65
|
+
:raises ConfigFileError: If the file is missing, of an unsupported format,
|
|
66
|
+
unparsable, or does not describe a mapping.
|
|
67
|
+
"""
|
|
68
|
+
if not os.path.exists(path):
|
|
69
|
+
raise ConfigFileError(f"Config file not found: {path}")
|
|
70
|
+
|
|
71
|
+
extension = os.path.splitext(path)[1].lower()
|
|
72
|
+
|
|
73
|
+
if extension in JSON_EXTENSIONS:
|
|
74
|
+
raw = _load_json(path)
|
|
75
|
+
elif extension in TOML_EXTENSIONS:
|
|
76
|
+
raw = _load_toml(path)
|
|
77
|
+
elif extension in YAML_EXTENSIONS:
|
|
78
|
+
raw = _load_yaml(path)
|
|
79
|
+
else:
|
|
80
|
+
raise ConfigFileError(
|
|
81
|
+
f"Unsupported config file extension '{extension or path}'. "
|
|
82
|
+
f"Supported extensions: {', '.join(SUPPORTED_EXTENSIONS)}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if not isinstance(raw, dict):
|
|
86
|
+
raise ConfigFileError(
|
|
87
|
+
f"Config file '{path}' must contain a mapping at its top level."
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return raw
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _load_json(path: str) -> Any:
|
|
94
|
+
try:
|
|
95
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
96
|
+
return json.load(f)
|
|
97
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as e:
|
|
98
|
+
raise ConfigFileError(f"Could not parse JSON config '{path}': {e}")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _load_toml(path: str) -> Any:
|
|
102
|
+
try:
|
|
103
|
+
with open(path, "rb") as f:
|
|
104
|
+
return tomllib.load(f)
|
|
105
|
+
except (OSError, tomllib.TOMLDecodeError) as e:
|
|
106
|
+
raise ConfigFileError(f"Could not parse TOML config '{path}': {e}")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _load_yaml(path: str) -> Any:
|
|
110
|
+
yaml = _yaml_module()
|
|
111
|
+
if yaml is None:
|
|
112
|
+
raise ConfigFileError(
|
|
113
|
+
"YAML config files need PyYAML, which is not installed. "
|
|
114
|
+
"Install it (pip install pyyaml) or use a .json / .toml config file instead."
|
|
115
|
+
)
|
|
116
|
+
try:
|
|
117
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
118
|
+
return yaml.safe_load(f)
|
|
119
|
+
except Exception as e:
|
|
120
|
+
# PyYAML raises its own YAMLError hierarchy; catching broadly keeps
|
|
121
|
+
# this import-optional module free of a yaml type import.
|
|
122
|
+
raise ConfigFileError(f"Could not parse YAML config '{path}': {e}")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def validate_project_config(config: Dict[str, Any]) -> List[str]:
|
|
126
|
+
"""
|
|
127
|
+
Validate a loaded configuration against the interactive-mode rules.
|
|
128
|
+
|
|
129
|
+
Reuses ``interactive.validators`` so a file-driven run is held to exactly
|
|
130
|
+
the same standard as an answered prompt.
|
|
131
|
+
|
|
132
|
+
:param config: Configuration dictionary
|
|
133
|
+
:return: List of human-readable error messages (empty when the config is valid)
|
|
134
|
+
"""
|
|
135
|
+
errors: List[str] = []
|
|
136
|
+
|
|
137
|
+
for key in REQUIRED_KEYS:
|
|
138
|
+
if not config.get(key):
|
|
139
|
+
errors.append(f"Missing required config key: '{key}'")
|
|
140
|
+
|
|
141
|
+
project_name = config.get("project_name")
|
|
142
|
+
if isinstance(project_name, str) and project_name:
|
|
143
|
+
is_valid, message = validate_project_name(project_name)
|
|
144
|
+
if not is_valid and message:
|
|
145
|
+
errors.append(message)
|
|
146
|
+
|
|
147
|
+
author_email = config.get("author_email")
|
|
148
|
+
if isinstance(author_email, str) and author_email:
|
|
149
|
+
if not validate_email_format(author_email):
|
|
150
|
+
errors.append(f"Invalid author email format: '{author_email}'")
|
|
151
|
+
|
|
152
|
+
# Feature selections are held to the catalog: an axis spelled in a shape
|
|
153
|
+
# the pipeline cannot read used to reach generation and produce a project
|
|
154
|
+
# whose ``main.py`` imported modules nobody wrote.
|
|
155
|
+
errors.extend(validate_project_config_schema(config))
|
|
156
|
+
|
|
157
|
+
return errors
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def load_normalized_project_config(path: str) -> Dict[str, Any]:
|
|
161
|
+
"""
|
|
162
|
+
Load a config file and return it in the canonical pipeline shape.
|
|
163
|
+
|
|
164
|
+
``load_project_config`` deliberately hands back exactly what the file
|
|
165
|
+
said (so ``--save-config`` round-trips byte for byte); this wrapper is
|
|
166
|
+
what the generation pipeline consumes, because every consumer of a
|
|
167
|
+
configuration must see the same normalised selections.
|
|
168
|
+
|
|
169
|
+
:param path: Path to the configuration file
|
|
170
|
+
:return: Normalised configuration dictionary
|
|
171
|
+
:raises ConfigFileError: If the file cannot be read, parsed or trusted
|
|
172
|
+
"""
|
|
173
|
+
raw = load_project_config(path)
|
|
174
|
+
try:
|
|
175
|
+
return normalize_project_config(raw)
|
|
176
|
+
except ConfigSchemaError as e:
|
|
177
|
+
raise ConfigFileError(f"Invalid project config '{path}': {e}")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def save_project_config(config: Dict[str, Any], path: str) -> None:
|
|
181
|
+
"""
|
|
182
|
+
Write a configuration dict to a JSON / TOML / YAML file.
|
|
183
|
+
|
|
184
|
+
:param config: Configuration dictionary produced by the interactive builder
|
|
185
|
+
:param path: Destination path; the extension selects the format
|
|
186
|
+
:raises ConfigFileError: If the format is unsupported or the write fails
|
|
187
|
+
"""
|
|
188
|
+
extension = os.path.splitext(path)[1].lower()
|
|
189
|
+
|
|
190
|
+
if extension in JSON_EXTENSIONS:
|
|
191
|
+
content = (
|
|
192
|
+
json.dumps(config, indent=2, sort_keys=True, ensure_ascii=False) + "\n"
|
|
193
|
+
)
|
|
194
|
+
elif extension in TOML_EXTENSIONS:
|
|
195
|
+
content = _dump_toml(config)
|
|
196
|
+
elif extension in YAML_EXTENSIONS:
|
|
197
|
+
yaml = _yaml_module()
|
|
198
|
+
if yaml is None:
|
|
199
|
+
raise ConfigFileError(
|
|
200
|
+
"Saving YAML config files needs PyYAML, which is not installed. "
|
|
201
|
+
"Use a .json / .toml path instead."
|
|
202
|
+
)
|
|
203
|
+
content = str(yaml.safe_dump(config, sort_keys=True, allow_unicode=True))
|
|
204
|
+
else:
|
|
205
|
+
raise ConfigFileError(
|
|
206
|
+
f"Unsupported config file extension '{extension or path}'. "
|
|
207
|
+
f"Supported extensions: {', '.join(SUPPORTED_EXTENSIONS)}"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
parent = os.path.dirname(os.path.abspath(path))
|
|
212
|
+
os.makedirs(parent, exist_ok=True)
|
|
213
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
214
|
+
f.write(content)
|
|
215
|
+
except OSError as e:
|
|
216
|
+
raise ConfigFileError(f"Could not write config file '{path}': {e}")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _dump_toml(config: Dict[str, Any]) -> str:
|
|
220
|
+
"""
|
|
221
|
+
Serialize a configuration dict to TOML.
|
|
222
|
+
|
|
223
|
+
Python 3.12 ships a TOML reader but no writer, and fastkit may not add a
|
|
224
|
+
runtime dependency for one. The interactive config only ever holds
|
|
225
|
+
strings, booleans, numbers, string lists and one level of nested tables
|
|
226
|
+
(``database``), which this covers.
|
|
227
|
+
"""
|
|
228
|
+
scalars: List[str] = []
|
|
229
|
+
tables: List[str] = []
|
|
230
|
+
|
|
231
|
+
for key in sorted(config):
|
|
232
|
+
value = config[key]
|
|
233
|
+
if isinstance(value, dict):
|
|
234
|
+
table_lines = [f"[{key}]"]
|
|
235
|
+
for sub_key in sorted(value):
|
|
236
|
+
table_lines.append(f"{sub_key} = {format_toml_value(value[sub_key])}")
|
|
237
|
+
tables.append("\n".join(table_lines))
|
|
238
|
+
else:
|
|
239
|
+
scalars.append(f"{key} = {format_toml_value(value)}")
|
|
240
|
+
|
|
241
|
+
sections = ["\n".join(scalars)] if scalars else []
|
|
242
|
+
sections.extend(tables)
|
|
243
|
+
return "\n\n".join(section for section in sections if section) + "\n"
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def format_toml_value(value: Any) -> str:
|
|
247
|
+
"""
|
|
248
|
+
Render a Python value as a TOML literal.
|
|
249
|
+
|
|
250
|
+
Shared with pyproject metadata injection so both writers escape and
|
|
251
|
+
quote values identically.
|
|
252
|
+
|
|
253
|
+
:param value: Value to render (bool / int / float / list / str)
|
|
254
|
+
:return: TOML literal string
|
|
255
|
+
"""
|
|
256
|
+
if isinstance(value, bool):
|
|
257
|
+
return "true" if value else "false"
|
|
258
|
+
if isinstance(value, (int, float)):
|
|
259
|
+
return str(value)
|
|
260
|
+
if isinstance(value, (list, tuple)):
|
|
261
|
+
return "[" + ", ".join(format_toml_value(item) for item in value) + "]"
|
|
262
|
+
escaped = str(value).replace("\\", "\\\\").replace('"', '\\"')
|
|
263
|
+
return f'"{escaped}"'
|
fastapi_fastkit/utils/main.py
CHANGED
|
@@ -356,3 +356,41 @@ def _pyproject_text_marks_fastkit(pyproject_path: str) -> bool:
|
|
|
356
356
|
if FASTKIT_DESCRIPTION_MARKER.lower() in content:
|
|
357
357
|
return True
|
|
358
358
|
return False
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def read_fastkit_metadata(project_dir: str) -> Dict[str, Any]:
|
|
362
|
+
"""Read the ``[tool.fastapi-fastkit]`` block of a generated project.
|
|
363
|
+
|
|
364
|
+
The block is the shared contract between generation (``init`` /
|
|
365
|
+
``startdemo``) and the commands that operate on an existing project
|
|
366
|
+
(``runserver``, ``addroute``): it records the template, preset,
|
|
367
|
+
package manager, selected features and โ most importantly โ the
|
|
368
|
+
``app_module`` entrypoint, so those commands no longer have to
|
|
369
|
+
re-derive the layout heuristically.
|
|
370
|
+
|
|
371
|
+
:param project_dir: Path to the generated project directory
|
|
372
|
+
:return: The metadata mapping, or an empty dict when the project has no
|
|
373
|
+
readable ``pyproject.toml`` / no fastkit block.
|
|
374
|
+
"""
|
|
375
|
+
pyproject_path = os.path.join(project_dir, "pyproject.toml")
|
|
376
|
+
if not os.path.exists(pyproject_path):
|
|
377
|
+
return {}
|
|
378
|
+
|
|
379
|
+
try:
|
|
380
|
+
with open(pyproject_path, "rb") as f:
|
|
381
|
+
data = tomllib.load(f)
|
|
382
|
+
except (OSError, tomllib.TOMLDecodeError, UnicodeDecodeError) as e:
|
|
383
|
+
debug_log(
|
|
384
|
+
f"Could not read fastkit metadata from {pyproject_path}: {e}", "warning"
|
|
385
|
+
)
|
|
386
|
+
return {}
|
|
387
|
+
|
|
388
|
+
tool_section = data.get("tool", {})
|
|
389
|
+
if not isinstance(tool_section, dict):
|
|
390
|
+
return {}
|
|
391
|
+
|
|
392
|
+
metadata = tool_section.get(FASTKIT_TOOL_SECTION, {})
|
|
393
|
+
if not isinstance(metadata, dict):
|
|
394
|
+
return {}
|
|
395
|
+
|
|
396
|
+
return dict(metadata)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: FastAPI-fastkit
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: Fast, easy-to-use starter kit for new users of Python and FastAPI
|
|
5
5
|
Author-Email: bnbong <bbbong9@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -11,6 +11,7 @@ Project-URL: Changelog, https://bnbong.github.io/FastAPI-fastkit/changelog/
|
|
|
11
11
|
Requires-Python: >=3.12
|
|
12
12
|
Requires-Dist: click>=8.1.7
|
|
13
13
|
Requires-Dist: rich>=13.9.2
|
|
14
|
+
Requires-Dist: jinja2>=3.1
|
|
14
15
|
Provides-Extra: dev
|
|
15
16
|
Requires-Dist: pytest>=9.0.3; extra == "dev"
|
|
16
17
|
Requires-Dist: pytest-cov>=6.2.1; extra == "dev"
|
|
@@ -19,10 +20,11 @@ Requires-Dist: pre-commit>=4.0.1; extra == "dev"
|
|
|
19
20
|
Requires-Dist: mypy>=1.12.0; extra == "dev"
|
|
20
21
|
Requires-Dist: isort>=5.13.2; extra == "dev"
|
|
21
22
|
Requires-Dist: pygments>=2.20.0; extra == "dev"
|
|
23
|
+
Requires-Dist: types-pyyaml>=6.0.12.20260408; extra == "dev"
|
|
22
24
|
Description-Content-Type: text/markdown
|
|
23
25
|
|
|
24
26
|
<p align="center">
|
|
25
|
-
<img align="top" width="70%" src="
|
|
27
|
+
<img align="top" width="70%" src=".github/fastkit_general_logo.png" alt="FastAPI-fastkit"/>
|
|
26
28
|
</p>
|
|
27
29
|
<p align="center">
|
|
28
30
|
<em><b>FastAPI-fastkit</b>: Fast, easy-to-use starter kit for new users of Python and FastAPI</em>
|
|
@@ -57,6 +59,8 @@ This project was inspired by the `SpringBoot initializer` & Python Django's `dja
|
|
|
57
59
|
- **๐ Automated template quality assurance** : Weekly automated testing ensures all templates remain functional and up-to-date
|
|
58
60
|
- **๐ Multiple project templates** : Choose from various pre-configured templates for different use cases (async CRUD, Docker, PostgreSQL, etc.)
|
|
59
61
|
- **๐ฆ Multiple package manager support** : Choose your preferred Python package manager (pip, uv, pdm, poetry) for dependency management
|
|
62
|
+
- **๐งพ Reproducible project configs** : Save an interactive session to a `.json` / `.toml` / `.yaml` file and replay it with `fastkit init --config`
|
|
63
|
+
- **๐ท๏ธ Self-describing projects** : Every generated project records its template, preset, package manager, entrypoint and selected features in a `[tool.fastapi-fastkit]` block that `runserver` and `addroute` read back
|
|
60
64
|
|
|
61
65
|
## Installation
|
|
62
66
|
|
|
@@ -78,17 +82,27 @@ $ pip install FastAPI-fastkit
|
|
|
78
82
|
```console
|
|
79
83
|
fastkit init [OPTIONS]
|
|
80
84
|
```
|
|
81
|
-
|
|
85
|
+
> [!TIP]
|
|
86
|
+
> Scaffolds an empty FastAPI project, creates a virtual environment, installs dependencies
|
|
87
|
+
|
|
82
88
|
- Key options:
|
|
83
89
|
- `--project-name`, `--author`, `--author-email`, `--description`
|
|
84
90
|
- `--package-manager` [pip|uv|pdm|poetry]
|
|
91
|
+
- `--config <path>`: create the project from a saved config file (`.json` / `.toml`, and `.yaml` when PyYAML is installed) with no prompts
|
|
92
|
+
- `--save-config <path>`: with `--interactive`, record the answers for later reuse
|
|
93
|
+
- `--dry-run`: print the files and packages that would be created, write nothing
|
|
94
|
+
- `--no-venv`: skip virtual environment creation (implies `--no-install`)
|
|
95
|
+
- `--no-install`: skip dependency installation
|
|
96
|
+
- `--yes` / `-y`: skip the "Overwrite these files?" confirmation when deploying in place
|
|
85
97
|
- Stack selection: `minimal` | `standard` | `full` (interactive)
|
|
86
98
|
|
|
87
99
|
### Create a project with interactive mode
|
|
88
100
|
```console
|
|
89
101
|
fastkit init --interactive
|
|
90
102
|
```
|
|
91
|
-
|
|
103
|
+
> [!TIP]
|
|
104
|
+
> Guided step-by-step project setup with intelligent feature selection
|
|
105
|
+
|
|
92
106
|
- Features:
|
|
93
107
|
- **Architecture preset**: `minimal` | `single-module` | `classic-layered` | `domain-starter` (default)
|
|
94
108
|
- **Database selection**: PostgreSQL, MySQL, MongoDB, Redis, SQLite
|
|
@@ -98,23 +112,33 @@ fastkit init --interactive
|
|
|
98
112
|
- **Monitoring**: Loguru, OpenTelemetry, Prometheus
|
|
99
113
|
- **Testing**: Basic (pytest), Coverage, Advanced (with faker, factory-boy)
|
|
100
114
|
- **Utilities**: CORS, Rate-Limiting, Pagination, WebSocket
|
|
115
|
+
- **Logging**: structured JSON logging with a request-id middleware
|
|
116
|
+
- **Migrations**: Alembic (async env, baseline revision)
|
|
117
|
+
- **Tooling**: ruff, pre-commit, GitHub Actions, devcontainer, Makefile (multi-select)
|
|
101
118
|
- **Deployment**: Docker, docker-compose with auto-generated configs
|
|
102
119
|
- **Package manager**: pip, uv, pdm, poetry
|
|
103
120
|
- **Custom packages**: Add your own dependencies
|
|
104
|
-
- Auto-generates (varies by preset
|
|
121
|
+
- Auto-generates (varies by preset - see [the matrix](https://bnbong.github.io/FastAPI-fastkit/reference/preset-feature-matrix/) for details):
|
|
105
122
|
- `main.py` regenerated from selected features for `minimal` / `single-module`; preserved as-shipped for `classic-layered` / `domain-starter`
|
|
106
123
|
- Database and authentication configuration files at preset-specific paths
|
|
107
124
|
- Docker deployment files (`Dockerfile`, `docker-compose.yml`) with the preset's correct uvicorn entrypoint
|
|
108
125
|
- Test configuration (pytest with coverage)
|
|
126
|
+
- `/health` and `/ready` endpoints on every generated project
|
|
127
|
+
- Real working code โ not just installed packages โ for background tasks, caching, WebSocket, pagination, OpenTelemetry, OAuth2 and session-based auth
|
|
128
|
+
- `--dry-run` previews the exact file tree a run would create, including logging/migrations/tooling artifacts
|
|
109
129
|
|
|
110
130
|
### Create a project from a template
|
|
111
131
|
```console
|
|
112
132
|
fastkit startdemo [TEMPLATE] [OPTIONS]
|
|
113
133
|
```
|
|
114
|
-
|
|
134
|
+
> [!TIP]
|
|
135
|
+
> Creates a project from a template (e.g., `fastapi-default`) and installs dependencies
|
|
136
|
+
|
|
115
137
|
- Key options:
|
|
116
138
|
- `--project-name`, `--author`, `--author-email`, `--description`
|
|
117
139
|
- `--package-manager` [pip|uv|pdm|poetry]
|
|
140
|
+
- `--dry-run`, `--no-venv`, `--no-install`, `--yes`/`-y` โ same meaning as on `init`
|
|
141
|
+
- Refuses to run if the target project directory already exists (`--dry-run` excepted)
|
|
118
142
|
- Tip: List available templates with `fastkit list-templates`
|
|
119
143
|
|
|
120
144
|
### Add a new route
|
|
@@ -136,6 +160,25 @@ fastkit runserver [OPTIONS]
|
|
|
136
160
|
fastkit list-templates
|
|
137
161
|
```
|
|
138
162
|
|
|
163
|
+
Available templates:
|
|
164
|
+
|
|
165
|
+
| Template | Description | Notes |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| [`fastapi-default`](src/fastapi_fastkit/fastapi_project_template/fastapi-default/README.md-tpl) | Simple FastAPI project with a classic layered layout | Good first choice |
|
|
168
|
+
| [`fastapi-empty`](src/fastapi_fastkit/fastapi_project_template/fastapi-empty/README.md-tpl) | Minimal FastAPI template | Base for `minimal` preset |
|
|
169
|
+
| [`fastapi-single-module`](src/fastapi_fastkit/fastapi_project_template/fastapi-single-module/README.md-tpl) | Single-file FastAPI app | Base for `single-module` preset |
|
|
170
|
+
| [`fastapi-domain-starter`](src/fastapi_fastkit/fastapi_project_template/fastapi-domain-starter/README.md-tpl) | Domain-oriented, pyproject-first starter for medium-sized APIs | Base for `domain-starter` preset |
|
|
171
|
+
| [`fastapi-auth-jwt`](src/fastapi_fastkit/fastapi_project_template/fastapi-auth-jwt/README.md-tpl) | JWT authentication with refresh-token rotation, argon2 hashing and scopes | New in v1.4.0 |
|
|
172
|
+
| [`fastapi-sqlmodel`](src/fastapi_fastkit/fastapi_project_template/fastapi-sqlmodel/README.md-tpl) | Async SQLModel + Alembic migrations + generic CRUD with pagination | New in v1.4.0 |
|
|
173
|
+
| [`fastapi-llm-agent`](src/fastapi_fastkit/fastapi_project_template/fastapi-llm-agent/README.md-tpl) | Streaming Claude chat agent (SSE) with a tool-call loop | New in v1.4.0 |
|
|
174
|
+
| [`fastapi-mcp`](src/fastapi_fastkit/fastapi_project_template/fastapi-mcp/README.md-tpl) | FastAPI app exposed as an MCP server | |
|
|
175
|
+
| [`fastapi-psql-orm`](src/fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/README.md-tpl) | Item management API with PostgreSQL, SQLModel, Alembic and docker-compose | Requires Docker |
|
|
176
|
+
| [`fastapi-custom-response`](src/fastapi_fastkit/fastapi_project_template/fastapi-custom-response/README.md-tpl) | Item management API with a custom response envelope, error handling and pagination | |
|
|
177
|
+
| [`fastapi-async-crud`](src/fastapi_fastkit/fastapi_project_template/fastapi-async-crud/README.md-tpl) | Async item management API | **Deprecated** โ use `fastapi-sqlmodel` |
|
|
178
|
+
| [`fastapi-dockerized`](src/fastapi_fastkit/fastapi_project_template/fastapi-dockerized/README.md-tpl) | Dockerized item management API | **Deprecated** โ use `fastapi-default` with the Docker option in `init --interactive` |
|
|
179
|
+
|
|
180
|
+
Deprecated templates still work but are no longer recommended starting points. See [Which starter should I choose?](https://bnbong.github.io/FastAPI-fastkit/user-guide/choosing-a-starter/) for a decision guide.
|
|
181
|
+
|
|
139
182
|
### Delete a project
|
|
140
183
|
```console
|
|
141
184
|
fastkit deleteproject <project_name>
|