opencode-config/.opencode/templates/backend/hooks/post_gen_project.py
Sergey c0e8ec816a
refactor(scripts): unify project contract + fix no_db polarity + frontend stack detection (#267)
* refactor(scripts): add project_contract.py single source of truth

* fix(spec-status): word-boundary regex for stack matching (uv!=uvicorn)

* feat(project-status): frontend stack detection + no_db support

* fix(template): cookiecutter use_db=no writes no_db=true marker

* fix(ci): ruff SIM300/PLC0415/W292/E501 in project_contract tests

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-08-04 23:20:11 +03:00

67 lines
No EOL
2.5 KiB
Python

"""Post-generation hook for the backend cookiecutter template.
Removes files that are conditional on the ``use_auth`` and ``use_db`` flags
so the rendered tree only contains the parts the user asked for.
- ``use_auth == "no"`` -> drop ``routes/auth.py``, ``services/auth_service.py``,
``models/user.py`` (hashed_password), and strip the auth dependency wiring.
- ``use_db == "no"`` -> drop ``db/``, ``migrations/``, ``connection.py``.
"""
from __future__ import annotations
import shutil
from pathlib import Path
PROJECT_DIR = Path.cwd()
def _remove(path: str) -> None:
"""Remove a file or directory relative to the generated project root."""
p = PROJECT_DIR / path
if p.is_dir():
shutil.rmtree(p, ignore_errors=True)
elif p.exists():
p.unlink()
def main() -> None:
use_auth = "{{ cookiecutter.use_auth }}"
use_db = "{{ cookiecutter.use_db }}"
pkg = "{{ cookiecutter.project_name }}"
if use_auth == "no":
_remove(f"src/{pkg}/api/v1/routes/auth.py")
_remove(f"src/{pkg}/services/auth_service.py")
_remove(f"tests/test_auth.py")
if use_db == "no":
# db is the root cause for the broken-conditional findings: files
# with unconditional ``from ...db.models.user import User`` must be
# stripped together with db/, otherwise the generated project
# fails to import (ImportError/NameError on startup).
_remove(f"src/{pkg}/db")
_remove("migrations")
_remove(f"src/{pkg}/services/user_service.py")
_remove(f"src/{pkg}/api/v1/routes/users.py")
_remove(f"src/{pkg}/api/v1/dependencies.py")
_remove(f"src/{pkg}/schemas/user.py")
_remove(f"tests/unit/test_user.py")
_remove(f"tests/unit/test_user_service.py")
_remove(f"tests/api/test_users.py")
if use_auth == "yes":
# auth_service imports User; strip it and its wiring too.
_remove(f"src/{pkg}/api/v1/routes/auth.py")
_remove(f"src/{pkg}/services/auth_service.py")
_remove(f"tests/test_auth.py")
# Write ``no_db = true`` into the existing ``[tool.project-status]``
# section so the project-status oracle skips the ``db/models``
# structure check for this no-db project (issue #266: no_db polarity
# fix). Append the key to the section at the end of the file.
pyproject = PROJECT_DIR / "pyproject.toml"
with open(pyproject, "a") as f:
f.write("\nno_db = true\n")
if __name__ == "__main__":
main()