diff --git a/.codex/skills/iti-flask-framework/SKILL.md b/.codex/skills/iti-flask-framework/SKILL.md index d7c3661..cf34494 100644 --- a/.codex/skills/iti-flask-framework/SKILL.md +++ b/.codex/skills/iti-flask-framework/SKILL.md @@ -49,6 +49,7 @@ iTi-Flask 是 FastAPI 后端框架基座。 - 模板变更在 `copier-template/`。 - Copier 模板源入口是仓库根目录 `copier.yml`,实际模板目录由 `_subdirectory: copier-template` 指定。 - 模板输出保持通用 FastAPI 业务后端骨架。 +- 模板生成项目固定使用 `app/` 作为 Python 顶层包,ASGI 入口固定为 `main.py`。 - 模板内不要写具体业务域知识。 - 模板结构、命令或生成文件变化时,同步更新: - `copier.yml` @@ -68,8 +69,8 @@ iTi-Flask 是 FastAPI 后端框架基座。 - 运行框架测试:`./scripts/iti.sh test` - 运行检查:`./scripts/iti.sh check` - 启动最小应用:`./scripts/iti.sh serve 8000` -- 生成业务项目:`./scripts/iti.sh make-app ../my-business-app my_business_app` -- 生成带系统包的业务项目:`./scripts/iti.sh make-system-app ../my-system-app my_system_app` +- 生成业务项目:`./scripts/iti.sh make-app ../my-business-app my-business-app` +- 生成带系统包的业务项目:`./scripts/iti.sh make-system-app ../my-system-app my-system-app` Windows 使用 `scripts\iti.cmd`。 diff --git a/README.md b/README.md index e6d6ec6..3458c89 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ app = create_app( ## 业务项目生成 ```bash -./iti.sh make-app ../my-business-app my_business_app +./iti.sh make-app ../my-business-app my-business-app cd ../my-business-app ./app.sh init ./app.sh serve 8000 @@ -91,7 +91,7 @@ cd ../my-business-app 带 `iti-system`: ```bash -./iti.sh make-system-app ../my-system-app my_system_app +./iti.sh make-system-app ../my-system-app my-system-app cd ../my-system-app ./app.sh init-system ``` diff --git a/copier-template/.codex/skills/{{ project_slug | lower | replace('_', '-') }}-project/SKILL.md.jinja b/copier-template/.codex/skills/{{ project_slug | lower | replace('_', '-') }}-project/SKILL.md.jinja index 9638a9e..e5ac7b8 100644 --- a/copier-template/.codex/skills/{{ project_slug | lower | replace('_', '-') }}-project/SKILL.md.jinja +++ b/copier-template/.codex/skills/{{ project_slug | lower | replace('_', '-') }}-project/SKILL.md.jinja @@ -1,6 +1,6 @@ --- name: {{ project_slug | lower | replace('_', '-') }}-project -description: "{{ project_name }} 业务项目 skill。用于当前由 iTi-Flask Copier 模板生成的业务后端项目,包括 app.py、config.py、app.sh/app.cmd、pyproject.toml、migrations、tests、modules、models、服务客户端、iTi-Flask 集成{% if include_system %}、iTi-System 注册{% endif %}和项目本地文档。不要写入具体业务域知识。" +description: "{{ project_name }} 业务项目 skill。用于当前由 iTi-Flask Copier 模板生成的业务后端项目,包括 main.py、config.py、app.sh/app.cmd、pyproject.toml、migrations、tests、modules、models、服务客户端、iTi-Flask 集成{% if include_system %}、iTi-System 注册{% endif %}和项目本地文档。不要写入具体业务域知识。" --- # {{ project_name }} 业务项目 @@ -27,10 +27,10 @@ description: "{{ project_name }} 业务项目 skill。用于当前由 iTi-Flask ## 项目结构 -- `app.py`:导入 `config`,注册模块,创建 FastAPI app。 +- `main.py`:导入 `config`,注册模块,创建 FastAPI app。 - `config.py`:项目本地配置映射。 -- `{{ project_slug }}/modules/`:业务模块。 -- `{{ project_slug }}/models/`:项目 SQLAlchemy 模型。 +- `app/modules/`:业务模块。 +- `app/models/`:项目 SQLAlchemy 模型。 - `migrations/`:项目自己的 Alembic migration 流。 - `tests/`:pytest 路由和行为测试。 - `app.sh`:Linux/macOS/Git Bash 命令入口。 @@ -48,7 +48,7 @@ description: "{{ project_name }} 业务项目 skill。用于当前由 iTi-Flask - `register_tasks(app)`:按需注册本地任务。 - `init_app(app)`:按需接入配置或服务客户端。 -业务模块优先放在 `{{ project_slug }}/modules//`。 +业务模块优先放在 `app/modules//`。 ## 运行规则 diff --git a/copier-template/README.md.jinja b/copier-template/README.md.jinja index 024390c..d385575 100644 --- a/copier-template/README.md.jinja +++ b/copier-template/README.md.jinja @@ -79,7 +79,7 @@ APP_ENV=prod ./app.sh migrate ./app.sh template-update ``` -模板更新会改 `app.py`、`config.py`、`app.sh`、`app.cmd`、示例模块、测试和项目 skill 等模板拥有的文件。 +模板更新会改 `main.py`、`config.py`、`app.sh`、`app.cmd`、示例模块、测试和项目 skill 等模板拥有的文件。 该命令跟随模板仓库 `HEAD`。 执行前先提交或暂存当前项目改动,执行后检查 diff。 diff --git a/copier-template/app.cmd.jinja b/copier-template/app.cmd.jinja index a3e4c87..4d36a45 100644 --- a/copier-template/app.cmd.jinja +++ b/copier-template/app.cmd.jinja @@ -128,7 +128,7 @@ if /I "%ARG1%"=="dev" ( if "%PORT%"=="" set "PORT=8000" set "APP_ENV=%ENV_NAME%" set "ITI_ENV=%ENV_NAME%" -uv run uvicorn app:app --reload --port "%PORT%" +uv run uvicorn main:app --reload --port "%PORT%" goto end :migrate @@ -157,7 +157,7 @@ uv run iti-system migrations sync --target migrations/versions goto end :system_seed -uv run iti-system seed system app:app +uv run iti-system seed system main:app goto end :init_system @@ -165,7 +165,7 @@ uv run iti-system migrations sync --target migrations/versions if errorlevel 1 goto end uv run alembic -c migrations/alembic.ini upgrade head if errorlevel 1 goto end -uv run iti-system seed system app:app +uv run iti-system seed system main:app goto end {% endif %}:init @@ -175,7 +175,7 @@ if errorlevel 1 goto end if errorlevel 1 goto end {% endif %}uv run alembic -c migrations/alembic.ini upgrade head if errorlevel 1 goto end -{% if include_system %}uv run iti-system seed system app:app +{% if include_system %}uv run iti-system seed system main:app {% endif %}goto end :end diff --git a/copier-template/app.sh.jinja b/copier-template/app.sh.jinja index c8ab447..99d1c7c 100644 --- a/copier-template/app.sh.jinja +++ b/copier-template/app.sh.jinja @@ -92,7 +92,7 @@ case "$command" in if [ "$env_name" = default ]; then env_name=dev fi - APP_ENV="$env_name" ITI_ENV="$env_name" uv run uvicorn app:app --reload --port "$port" + APP_ENV="$env_name" ITI_ENV="$env_name" uv run uvicorn main:app --reload --port "$port" ;; migrate) uv run alembic -c migrations/alembic.ini upgrade head @@ -115,18 +115,18 @@ case "$command" in uv run iti-system migrations sync --target migrations/versions ;; system-seed) - uv run iti-system seed system app:app + uv run iti-system seed system main:app ;; init-system) uv run iti-system migrations sync --target migrations/versions uv run alembic -c migrations/alembic.ini upgrade head - uv run iti-system seed system app:app + uv run iti-system seed system main:app ;; {% endif %} init) uv sync --extra dev {% if include_system %} uv run iti-system migrations sync --target migrations/versions {% endif %} uv run alembic -c migrations/alembic.ini upgrade head -{% if include_system %} uv run iti-system seed system app:app +{% if include_system %} uv run iti-system seed system main:app {% endif %} ;; *) echo "未知命令:$command" >&2 diff --git a/copier-template/{{ project_slug }}/__init__.py.jinja b/copier-template/app/__init__.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/__init__.py.jinja rename to copier-template/app/__init__.py.jinja diff --git a/copier-template/{{ project_slug }}/models/__init__.py.jinja b/copier-template/app/models/__init__.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/models/__init__.py.jinja rename to copier-template/app/models/__init__.py.jinja diff --git a/copier-template/{{ project_slug }}/models/example/__init__.py.jinja b/copier-template/app/models/example/__init__.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/models/example/__init__.py.jinja rename to copier-template/app/models/example/__init__.py.jinja diff --git a/copier-template/{{ project_slug }}/models/example/example.py.jinja b/copier-template/app/models/example/example.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/models/example/example.py.jinja rename to copier-template/app/models/example/example.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/__init__.py.jinja b/copier-template/app/modules/__init__.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/__init__.py.jinja rename to copier-template/app/modules/__init__.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/__init__.py.jinja b/copier-template/app/modules/example/__init__.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/__init__.py.jinja rename to copier-template/app/modules/example/__init__.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/module.py.jinja b/copier-template/app/modules/example/module.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/module.py.jinja rename to copier-template/app/modules/example/module.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/public.py.jinja b/copier-template/app/modules/example/public.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/public.py.jinja rename to copier-template/app/modules/example/public.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/routes.py.jinja b/copier-template/app/modules/example/routes.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/routes.py.jinja rename to copier-template/app/modules/example/routes.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/schemas.py.jinja b/copier-template/app/modules/example/schemas.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/schemas.py.jinja rename to copier-template/app/modules/example/schemas.py.jinja diff --git a/copier-template/{{ project_slug }}/modules/example/service.py.jinja b/copier-template/app/modules/example/service.py.jinja similarity index 100% rename from copier-template/{{ project_slug }}/modules/example/service.py.jinja rename to copier-template/app/modules/example/service.py.jinja diff --git a/copier-template/config.py.jinja b/copier-template/config.py.jinja index cd2230c..2f7f7bd 100644 --- a/copier-template/config.py.jinja +++ b/copier-template/config.py.jinja @@ -33,7 +33,7 @@ class TestConfig(BaseConfig): f"{os.getenv('MYSQL_PASSWORD', 'password')}@" f"{os.getenv('MYSQL_HOST', '127.0.0.1')}:" f"{os.getenv('MYSQL_PORT', '3306')}/" - f"{os.getenv('MYSQL_DATABASE', 'hsyh_mes_phase2_test')}?charset=utf8mb4", + f"{os.getenv('MYSQL_DATABASE', 'app_test')}?charset=utf8mb4", ), base_dir=BASE_DIR, ratelimit_enabled=False, diff --git a/copier-template/app.py.jinja b/copier-template/main.py.jinja similarity index 84% rename from copier-template/app.py.jinja rename to copier-template/main.py.jinja index 36df36e..dddeb78 100644 --- a/copier-template/app.py.jinja +++ b/copier-template/main.py.jinja @@ -5,7 +5,7 @@ from iti import create_app {% endif -%} from config import config -from {{ project_slug }}.modules.example.module import ExampleModule +from app.modules.example.module import ExampleModule modules = [ diff --git a/copier-template/migrations/env.py.jinja b/copier-template/migrations/env.py.jinja index 2a9ca9c..3dabc06 100644 --- a/copier-template/migrations/env.py.jinja +++ b/copier-template/migrations/env.py.jinja @@ -16,7 +16,7 @@ from config import config as app_config from iti.db import Base from iti.exchange import models as _exchange_models -from {{ project_slug }}.models import import_models +from app.models import import_models import_models() diff --git a/copier-template/pyproject.toml.jinja b/copier-template/pyproject.toml.jinja index 789a94f..96372f2 100644 --- a/copier-template/pyproject.toml.jinja +++ b/copier-template/pyproject.toml.jinja @@ -21,7 +21,7 @@ dev = [ ] [tool.setuptools.packages.find] -include = ["{{ project_slug }}*"] +include = ["app*"] [tool.pytest.ini_options] pythonpath = ["."] diff --git a/copier-template/tests/test_example.py.jinja b/copier-template/tests/test_example.py.jinja index ef0dfc1..caa8829 100644 --- a/copier-template/tests/test_example.py.jinja +++ b/copier-template/tests/test_example.py.jinja @@ -1,6 +1,6 @@ from fastapi.testclient import TestClient -from app import app +from main import app def test_health(): diff --git a/copier.yml b/copier.yml index dca4663..afea99b 100644 --- a/copier.yml +++ b/copier.yml @@ -15,8 +15,8 @@ project_name: project_slug: type: str - help: 业务项目 Python 包名 - default: iti_business_app + help: 业务项目发行包名来源 + default: iti-business-app framework_git: type: str diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 6ca8f5d..0517e6d 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -6,8 +6,8 @@ ## 环境选择 ```bash -ITI_ENV=dev uv run uvicorn app:app --reload -ITI_ENV=prod uv run uvicorn app:app +ITI_ENV=dev uv run uvicorn main:app --reload +ITI_ENV=prod uv run uvicorn main:app ``` 也可以显式传入: diff --git a/docs/COPIER_TEMPLATE.md b/docs/COPIER_TEMPLATE.md index b33db63..67d2e3e 100644 --- a/docs/COPIER_TEMPLATE.md +++ b/docs/COPIER_TEMPLATE.md @@ -23,7 +23,7 @@ copier-template/.codex/skills/{{ project_slug | lower | replace('_', '-') }}-pro ## 生成 ```bash -./iti.sh make-app ../my-business-app my_business_app +./iti.sh make-app ../my-business-app my-business-app cd ../my-business-app ./app.sh init ./app.sh serve 8000 @@ -32,7 +32,7 @@ cd ../my-business-app Windows: ```bat -iti.cmd make-app ..\my-business-app my_business_app +iti.cmd make-app ..\my-business-app my-business-app cd ..\my-business-app app.cmd init app.cmd serve 8000 @@ -43,7 +43,7 @@ app.cmd serve 8000 | 参数 | 说明 | | --- | --- | | `project_name` | 业务项目显示名称 | -| `project_slug` | 业务项目 Python 包名 | +| `project_slug` | 业务项目发行包名来源 | | `framework_git` | iTi-Flask Git 地址 | | `framework_tag` | iTi-Flask Git tag | | `include_system` | 是否引入 iTi-System | @@ -55,7 +55,7 @@ app.cmd serve 8000 ## 生成内容 -- `app.py` +- `main.py` - `config.py` - `pyproject.toml` - `migrations/` @@ -138,5 +138,5 @@ app.cmd init-system 模板更新前,业务项目工作区必须干净。 执行后检查 diff,再运行测试。 -模板拥有的文件包括 `app.py`、`config.py`、`app.sh`、`app.cmd`、`pyproject.toml`、`migrations/`、示例模块、示例测试、README 和项目 skill。 +模板拥有的文件包括 `main.py`、`config.py`、`app.sh`、`app.cmd`、`pyproject.toml`、`migrations/`、示例模块、示例测试、README 和项目 skill。 业务项目自己的模块、模型、API 文档和业务 README 由业务项目维护。 diff --git a/docs/README.md b/docs/README.md index 7b512e6..42bdd5e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,7 +19,7 @@ AI 修改框架时优先读 `.codex/skills/iti-flask-framework/SKILL.md`。 ./iti.sh install ./iti.sh test ./iti.sh check -./iti.sh make-app ../my-business-app my_business_app -./iti.sh make-system-app ../my-system-app my_system_app +./iti.sh make-app ../my-business-app my-business-app +./iti.sh make-system-app ../my-system-app my-system-app ./iti.sh release ``` diff --git a/docs/SEEDS.md b/docs/SEEDS.md index b542788..48251d1 100644 --- a/docs/SEEDS.md +++ b/docs/SEEDS.md @@ -16,7 +16,7 @@ 系统包提供: ```bash -uv run iti-system seed system app:app +uv run iti-system seed system main:app ``` 它会写入默认角色、管理员、系统菜单、字典和配置。 diff --git a/docs/TESTING_DEPLOYMENT.md b/docs/TESTING_DEPLOYMENT.md index 23893ee..42f74ad 100644 --- a/docs/TESTING_DEPLOYMENT.md +++ b/docs/TESTING_DEPLOYMENT.md @@ -33,8 +33,8 @@ CREATE DATABASE my_business_app_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unico export DATABASE_URL='mysql+pymysql://root:password@127.0.0.1:3306/iti_test?charset=utf8mb4' uv run alembic upgrade head uv run iti-system migrations sync --target migrations/versions -uv run iti-system seed system app:app -uv run uvicorn app:app --reload +uv run iti-system seed system main:app +uv run uvicorn main:app --reload ``` 验证: @@ -65,13 +65,13 @@ healthcheck: 简单部署: ```bash -uv run uvicorn app:app --host 0.0.0.0 --port 8000 +uv run uvicorn main:app --host 0.0.0.0 --port 8000 ``` 多 worker: ```bash -uv run gunicorn app:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000 +uv run gunicorn main:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000 ``` `tasks_enabled=True` 时不要在多个 worker 同时启用调度。 diff --git a/scripts/iti.cmd b/scripts/iti.cmd index e8750b5..e109cde 100644 --- a/scripts/iti.cmd +++ b/scripts/iti.cmd @@ -52,16 +52,16 @@ echo migrate 执行当前仓库 Alembic upgrade head echo migration ^<说明^> 生成 migration,说明建议以作者名开头 echo heads 查看 Alembic heads echo current 查看当前 Alembic 版本 -echo make-app ^<目录^> [包名] 从当前框架仓库模板生成业务项目 -echo make-system-app ^<目录^> [包名] 生成带 iti-system 的业务项目 +echo make-app ^<目录^> [发行名] 从当前框架仓库模板生成业务项目 +echo make-system-app ^<目录^> [发行名] 生成带 iti-system 的业务项目 echo release [版本] 发布框架:测试、改版本、提交、打 tag、推送 echo. echo 示例: echo iti.cmd install echo iti.cmd test echo iti.cmd serve 8000 -echo iti.cmd make-app ..\hsyh-erp hsyh_erp -echo iti.cmd make-system-app ..\hsyh-mes-phase2 hsyh_mes_phase2 +echo iti.cmd make-app ..\hsyh-erp-phase2 hsyh-erp-phase2 +echo iti.cmd make-system-app ..\hsyh-mes-phase2 hsyh-mes-phase2 popd >nul exit /b 0 @@ -137,17 +137,16 @@ goto make_project :make_project set "TARGET=%~1" -set "PACKAGE=%~2" +set "DIST_NAME=%~2" if "%TARGET%"=="" ( - echo 缺少目标目录。示例:iti.cmd make-app ..\my-app my_app 1>&2 + echo 缺少目标目录。示例:iti.cmd make-app ..\my-app my-app 1>&2 exit /b 2 ) -if "%PACKAGE%"=="" ( - for %%I in ("%TARGET%") do set "PACKAGE=%%~nxI" - set "PACKAGE=!PACKAGE:-=_!" +if "%DIST_NAME%"=="" ( + for %%I in ("%TARGET%") do set "DIST_NAME=%%~nxI" ) for %%I in ("%TARGET%") do set "PROJECT_NAME=%%~nxI" -uvx copier copy --defaults --vcs-ref HEAD "%CD%" "%TARGET%" -d project_name="!PROJECT_NAME!" -d project_slug="!PACKAGE!" -d include_system="%INCLUDE_SYSTEM%" +uvx copier copy --defaults --vcs-ref HEAD "%CD%" "%TARGET%" -d project_name="!PROJECT_NAME!" -d project_slug="!DIST_NAME!" -d include_system="%INCLUDE_SYSTEM%" goto end :end diff --git a/scripts/iti.sh b/scripts/iti.sh index 83843f4..fbf9a29 100644 --- a/scripts/iti.sh +++ b/scripts/iti.sh @@ -30,16 +30,16 @@ iTi-Flask 开发脚本 migration <说明> 生成 migration,说明建议以作者名开头 heads 查看 Alembic heads current 查看当前 Alembic 版本 - make-app <目录> [包名] 从当前框架仓库模板生成业务项目 - make-system-app <目录> [包名] 生成带 iti-system 的业务项目 + make-app <目录> [发行名] 从当前框架仓库模板生成业务项目 + make-system-app <目录> [发行名] 生成带 iti-system 的业务项目 release [版本] 发布框架:测试、改版本、提交、打 tag、推送 示例: ./iti.sh install ./iti.sh test ./iti.sh serve 8000 - ./iti.sh make-app ../hsyh-erp hsyh_erp - ./iti.sh make-system-app ../hsyh-mes-phase2 hsyh_mes_phase2 + ./iti.sh make-app ../hsyh-erp-phase2 hsyh-erp-phase2 + ./iti.sh make-system-app ../hsyh-mes-phase2 hsyh-mes-phase2 说明: - 默认生成项目使用 copier-template 里的 Git 依赖配置。 @@ -90,13 +90,13 @@ case "$command" in ;; make-app|make-system-app) target=${1:-} - package=${2:-} + dist_name=${2:-} if [ -z "$target" ]; then - echo "缺少目标目录。示例:./iti.sh make-app ../my-app my_app" >&2 + echo "缺少目标目录。示例:./iti.sh make-app ../my-app my-app" >&2 exit 2 fi - if [ -z "$package" ]; then - package=$(basename "$target" | tr '-' '_') + if [ -z "$dist_name" ]; then + dist_name=$(basename "$target") fi include_system=false if [ "$command" = "make-system-app" ]; then @@ -104,7 +104,7 @@ case "$command" in fi uvx copier copy --defaults --vcs-ref HEAD "$ROOT_DIR" "$target" \ -d project_name="$(basename "$target")" \ - -d project_slug="$package" \ + -d project_slug="$dist_name" \ -d include_system="$include_system" ;; *)