create-dwy 0.5.1 → 0.6.0
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.
- package/bin/index.js +1 -1
- package/package.json +2 -2
- package/src/create.js +61 -37
- package/src/sync.js +212 -61
- package/templates/claude-global/CLAUDE.md +92 -0
- package/templates/claude-global/rules/dwy-android-core.md +610 -0
- package/templates/claude-global/rules/dwy-api-design.md +110 -0
- package/templates/claude-global/rules/dwy-db-migration.md +46 -0
- package/templates/claude-global/rules/dwy-flutter-core.md +564 -0
- package/templates/claude-global/rules/dwy-flutter-network.md +222 -0
- package/templates/claude-global/rules/dwy-flutter-router.md +97 -0
- package/templates/claude-global/rules/dwy-flutter-testing.md +94 -0
- package/templates/claude-global/rules/dwy-git-commit-convention.md +82 -0
- package/templates/claude-global/rules/dwy-git-security.md +53 -0
- package/templates/claude-global/rules/dwy-payload-limits.md +178 -0
- package/templates/claude-global/rules/{prefer-open-source.md → dwy-prefer-open-source.md} +4 -0
- package/templates/claude-global/rules/dwy-project-structure.md +181 -0
- package/templates/claude-global/rules/{python-code-style.md → dwy-python-core.md} +292 -358
- package/templates/claude-global/rules/dwy-python-fastapi.md +272 -0
- package/templates/claude-global/rules/dwy-python-orm.md +61 -0
- package/templates/claude-global/rules/{backend-security.md → dwy-python-security.md} +99 -72
- package/templates/claude-global/rules/dwy-python-testing.md +53 -0
- package/templates/claude-global/rules/{server-security.md → dwy-server-security.md} +1 -2
- package/templates/claude-global/rules/dwy-tdd-development.md +70 -0
- package/templates/claude-global/rules/dwy-tech-stack.md +60 -0
- package/templates/claude-global/rules/dwy-vue-api.md +146 -0
- package/templates/claude-global/rules/{vue-code-style.md → dwy-vue-core.md} +338 -152
- package/templates/claude-global/rules/dwy-vue-pinia.md +75 -0
- package/templates/claude-global/rules/dwy-vue-testing.md +102 -0
- package/templates/claude-global/skills/dwy-deploy-audit/SKILL.md +481 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-data.md +117 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-network.md +74 -0
- package/templates/claude-global/skills/dwy-deploy-audit/references/checks-runtime.md +184 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_base.sh +39 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_capacity.sh +278 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_db.sh +122 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_docker.sh +249 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_env.sh +64 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_https.sh +60 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_logs.sh +209 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_nginx.sh +92 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_resilience.sh +157 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_secrets.sh +327 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_services.sh +77 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/check_ssh.sh +56 -0
- package/templates/claude-global/skills/dwy-deploy-audit/scripts/run_all.sh +105 -0
- package/templates/claude-global/skills/dwy-docker/SKILL.md +187 -0
- package/templates/claude-global/skills/dwy-docker/references/ask-templates.md +142 -0
- package/templates/claude-global/skills/dwy-docker/references/templates.md +479 -0
- package/templates/claude-global/skills/dwy-docker/references/version-rules.md +76 -0
- package/templates/claude-global/skills/dwy-docker/scripts/query_dockerhub.py +204 -0
- package/templates/claude-global/skills/dwy-docker/scripts/scan_images.sh +185 -0
- package/templates/claude-global/skills/dwy-eapi/SKILL.md +433 -0
- package/templates/claude-global/skills/dwy-eapi/references/tasks-integration-guide.md +387 -0
- package/templates/claude-global/skills/dwy-ekit/SKILL.md +85 -0
- package/templates/claude-global/skills/dwy-ekit/references/data.md +135 -0
- package/templates/claude-global/skills/dwy-ekit/references/form.md +68 -0
- package/templates/claude-global/skills/dwy-ekit/references/request.md +183 -0
- package/templates/claude-global/skills/dwy-ekit/references/ui.md +109 -0
- package/templates/claude-global/skills/{dwy-frontend-eui → dwy-eui}/SKILL.md +129 -15
- package/templates/claude-global/skills/dwy-eui/references/eui-design-guide.md +257 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-integration-guide.md +302 -0
- package/templates/claude-global/skills/dwy-eui/references/eui-landing-design-guide.md +437 -0
- package/templates/claude-global/skills/dwy-fullstack-scaffold/SKILL.md +214 -0
- package/templates/claude-global/skills/dwy-mirror-source/SKILL.md +275 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/dockerfile-snippets.md +228 -0
- package/templates/claude-global/skills/dwy-mirror-source/references/mirror-providers.md +150 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/__pycache__/check_mirrors.cpython-313.pyc +0 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/apply_mirrors.py +666 -0
- package/templates/claude-global/skills/dwy-mirror-source/scripts/check_mirrors.py +868 -0
- package/templates/claude-global/skills/dwy-pentest/SKILL.md +344 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__init__.py +1 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/__init__.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/config.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/executor.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/severity.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/__pycache__/validator.cpython-311.pyc +0 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/config.py +109 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/executor.py +157 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/severity.py +96 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/lib/validator.py +113 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_auth.py +289 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_recon.py +217 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_report.py +343 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_scan.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_ssl.py +208 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_vuln.py +205 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pentest_web.py +330 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/pyproject.toml +14 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/setup_tools.sh +97 -0
- package/templates/claude-global/skills/dwy-pentest/scripts/uv.lock +415 -0
- package/templates/claude-global/skills/{dwy-release → dwy-publish}/SKILL.md +42 -18
- package/templates/claude-global/skills/dwy-vue-core/SKILL.md +890 -0
- package/templates/project/backend/.dwy.hbs +5 -0
- package/templates/project/backend/.python-version +1 -0
- package/templates/project/backend/CLAUDE.md.hbs +40 -0
- package/templates/project/{web/backend → backend}/alembic/script.py.mako +2 -0
- package/templates/project/{web/backend → backend}/alembic.ini.hbs +0 -1
- package/templates/project/backend/deploy.sh.hbs +18 -0
- package/templates/project/{web → backend}/docker-compose.prod.yml.hbs +1 -1
- package/templates/project/{web/backend → backend}/pyproject.toml.hbs +4 -5
- package/templates/project/{web/backend → backend}/src/app/config.py.hbs +1 -1
- package/templates/project/backend/src/app/database.py +10 -0
- package/templates/project/backend/src/app/dependencies.py +5 -0
- package/templates/project/{web/backend → backend}/src/app/main.py.hbs +3 -3
- package/templates/project/backend/src/app/models/base.py +5 -0
- package/templates/project/web/CLAUDE.md.hbs +29 -36
- package/templates/project/web/{frontend → apps/web}/index.html.hbs +1 -0
- package/templates/project/web/{frontend → apps/web}/package.json.hbs +4 -3
- package/templates/project/web/apps/web/src/App.vue +9 -0
- package/templates/project/web/apps/web/src/api/client.ts +5 -0
- package/templates/project/web/apps/web/src/composables/.gitkeep +0 -0
- package/templates/project/web/apps/web/src/layouts/DefaultLayout.vue +8 -0
- package/templates/project/web/{frontend → apps/web}/src/router/index.ts +1 -1
- package/templates/project/web/{frontend → apps/web}/src/stores/auth.ts +4 -2
- package/templates/project/web/apps/web/src/style.css +2 -0
- package/templates/project/web/apps/web/src/types/router.d.ts +8 -0
- package/templates/project/web/apps/web/src/views/HomeView.vue +8 -0
- package/templates/project/web/apps/web/tsconfig.app.json +18 -0
- package/templates/project/web/apps/web/tsconfig.json +6 -0
- package/templates/project/web/{frontend → apps/web}/vite.config.ts.hbs +7 -1
- package/templates/project/web/package.json.hbs +16 -0
- package/templates/project/web/packages/.gitkeep +0 -0
- package/templates/project/web/pnpm-workspace.yaml +3 -0
- package/templates/claude-global/hooks/post-sync-claude-global.sh +0 -72
- package/templates/claude-global/rules/agent-team-execution.md +0 -138
- package/templates/claude-global/rules/agent-team-patterns.md +0 -157
- package/templates/claude-global/rules/git-commit-convention.md +0 -106
- package/templates/claude-global/rules/git-security.md +0 -144
- package/templates/claude-global/skills/dwy-backend-base/SKILL.md +0 -279
- package/templates/claude-global/skills/dwy-frontend-core/SKILL.md +0 -181
- package/templates/project/web/.claude/commands/deploy.md +0 -4
- package/templates/project/web/backend/src/app/models/base.py +0 -5
- package/templates/project/web/deploy.sh.hbs +0 -113
- package/templates/project/web/frontend/src/App.vue +0 -3
- package/templates/project/web/frontend/src/api/client.ts +0 -13
- package/templates/project/web/frontend/src/style.css +0 -1
- package/templates/project/web/frontend/src/views/HomeView.vue +0 -5
- package/templates/project/web/frontend/tsconfig.app.json +0 -14
- package/templates/project/web/frontend/tsconfig.json +0 -4
- /package/templates/{project/web/backend → claude-global/skills/dwy-pentest/scripts}/.python-version +0 -0
- /package/templates/project/{web/backend → backend}/Dockerfile +0 -0
- /package/templates/project/{web/backend → backend}/alembic/env.py.hbs +0 -0
- /package/templates/{claude-global/skills → project/backend/alembic/versions}/.gitkeep +0 -0
- /package/templates/project/{web → backend}/docker-compose.dev.yml.hbs +0 -0
- /package/templates/project/{web/backend → backend}/src/app/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/models/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/routers/health.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/schemas/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/src/app/services/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/__init__.py +0 -0
- /package/templates/project/{web/backend → backend}/tests/conftest.py.hbs +0 -0
- /package/templates/project/{web/backend/alembic/versions → mobile}/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/components/.gitkeep +0 -0
- /package/templates/project/web/{frontend → apps/web}/src/main.ts +0 -0
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Agent 并行模式速查表
|
|
2
|
-
|
|
3
|
-
常见任务的 Agent 并行分工模板。执行前对照此表选择合适的模式。
|
|
4
|
-
|
|
5
|
-
## 一、任务级并行模式
|
|
6
|
-
|
|
7
|
-
### 模式 1:批量创建(N 路并行)
|
|
8
|
-
|
|
9
|
-
**场景:** 创建多个独立的组件/页面/测试/demo
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
示例:"给 5 个组件写 demo 页面"
|
|
13
|
-
|
|
14
|
-
Agent-1 (worktree) → ComponentA demo
|
|
15
|
-
Agent-2 (worktree) → ComponentB demo
|
|
16
|
-
Agent-3 (worktree) → ComponentC demo
|
|
17
|
-
Agent-4 (worktree) → ComponentD demo
|
|
18
|
-
Agent-5 (worktree) → ComponentE demo
|
|
19
|
-
→ 全部完成后 code-reviewer 审查
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
**要点:**
|
|
23
|
-
- 每个 Agent 使用 `isolation: "worktree"`
|
|
24
|
-
- 每个 Agent 的 prompt 包含组件的 API 说明和 demo 规范
|
|
25
|
-
- 风险等级:低,直接执行
|
|
26
|
-
|
|
27
|
-
### 模式 2:研究 + 实现(2 阶段流水线)
|
|
28
|
-
|
|
29
|
-
**场景:** 需要先了解代码再动手修改
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
示例:"修复 EForm 组件的验证 bug"
|
|
33
|
-
|
|
34
|
-
阶段 1(并行研究):
|
|
35
|
-
Agent-Explore → 分析 EForm 组件代码结构和数据流
|
|
36
|
-
Agent-Explore → 搜索相关测试和使用示例
|
|
37
|
-
Agent-Explore → 查看 git 历史和相关 issue
|
|
38
|
-
|
|
39
|
-
阶段 2(串行实现):
|
|
40
|
-
基于研究结果,主线程或单 Agent 实现修复
|
|
41
|
-
|
|
42
|
-
阶段 3(并行验证):
|
|
43
|
-
Agent → 运行测试
|
|
44
|
-
Agent → code-review 变更
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**要点:**
|
|
48
|
-
- 阶段 1 的 Agent 全部用 `subagent_type: "Explore"`
|
|
49
|
-
- 阶段 2 必须等阶段 1 全部完成
|
|
50
|
-
- 风险等级:中,阶段 2 前需确认方案
|
|
51
|
-
|
|
52
|
-
### 模式 3:多模块同步修改
|
|
53
|
-
|
|
54
|
-
**场景:** 一个功能涉及多个独立模块的修改
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
示例:"给所有 API 模块添加分页参数"
|
|
58
|
-
|
|
59
|
-
Agent-1 (worktree) → 修改 user API 模块
|
|
60
|
-
Agent-2 (worktree) → 修改 order API 模块
|
|
61
|
-
Agent-3 (worktree) → 修改 product API 模块
|
|
62
|
-
→ code-reviewer 审查一致性
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
**要点:**
|
|
66
|
-
- 每个 Agent 必须收到统一的修改规范(参数命名、类型定义)
|
|
67
|
-
- 使用 worktree 隔离
|
|
68
|
-
- 风险等级:中,执行前确认修改规范
|
|
69
|
-
|
|
70
|
-
### 模式 4:前后端同步开发
|
|
71
|
-
|
|
72
|
-
**场景:** 接口契约已定,前后端可以同时写
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
示例:"新增用户导出功能"
|
|
76
|
-
|
|
77
|
-
Agent-1 (worktree) → 后端 API + service 实现
|
|
78
|
-
Agent-2 (worktree) → 前端页面 + API 调用
|
|
79
|
-
→ code-reviewer 审查接口契约一致性
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
**要点:**
|
|
83
|
-
- 两个 Agent 必须收到相同的接口契约定义(URL、参数、响应格式)
|
|
84
|
-
- 风险等级:中,确认接口契约后执行
|
|
85
|
-
|
|
86
|
-
## 二、步骤级并行模式
|
|
87
|
-
|
|
88
|
-
### 模式 A:并行信息收集
|
|
89
|
-
|
|
90
|
-
在执行任何任务前,将独立的信息收集步骤并行化:
|
|
91
|
-
|
|
92
|
-
```
|
|
93
|
-
同一消息中发起:
|
|
94
|
-
Grep → 搜索相关代码引用
|
|
95
|
-
Glob → 查找相关文件
|
|
96
|
-
Read → 读取配置文件
|
|
97
|
-
Agent(Explore) → 分析依赖关系
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 模式 B:并行验证
|
|
101
|
-
|
|
102
|
-
修改完成后,将独立的验证步骤并行化:
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
同一消息中发起:
|
|
106
|
-
Bash → 运行单元测试
|
|
107
|
-
Bash → 运行 lint 检查
|
|
108
|
-
Bash → 运行类型检查
|
|
109
|
-
Bash → 运行构建
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 模式 C:并行文档/测试补充
|
|
113
|
-
|
|
114
|
-
主要代码完成后,并行补充配套文件:
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
同一消息中发起:
|
|
118
|
-
Agent → 写单元测试
|
|
119
|
-
Agent → 更新相关文档
|
|
120
|
-
Agent → 更新 changelog
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## 三、反模式(禁止使用)
|
|
124
|
-
|
|
125
|
-
| 反模式 | 问题 | 正确做法 |
|
|
126
|
-
|--------|------|---------|
|
|
127
|
-
| 多 Agent 改同一文件 | 冲突、覆盖 | 串行修改或拆分文件职责 |
|
|
128
|
-
| 无上下文的 Agent | 产出质量差 | prompt 必须自包含 |
|
|
129
|
-
| 链式依赖硬并行 | B 依赖 A 的输出却并行 | 识别依赖,串行执行 |
|
|
130
|
-
| 超过 5 个 Agent 同时派出 | 难以管理、context 爆炸 | 单批最多 5 个 Agent |
|
|
131
|
-
| 跳过 review 直接提交 | 质量无保障 | 遵循 review 闭环 |
|
|
132
|
-
|
|
133
|
-
## 四、Agent 数量指南
|
|
134
|
-
|
|
135
|
-
| 场景 | 建议 Agent 数 |
|
|
136
|
-
|------|-------------|
|
|
137
|
-
| 批量创建同质文件 | 每个文件 1 个,上限 5 个/批 |
|
|
138
|
-
| 并行研究 | 2-3 个 Explore Agent |
|
|
139
|
-
| 多模块修改 | 每个模块 1 个,上限 4 个/批 |
|
|
140
|
-
| 前后端同步 | 2 个 |
|
|
141
|
-
| 步骤级并行工具调用 | 不限(Grep/Glob/Read 等轻量调用尽量并行) |
|
|
142
|
-
|
|
143
|
-
超过 5 个 Agent 的任务,分批执行:先派第一批,完成后再派第二批。
|
|
144
|
-
|
|
145
|
-
## 五、Worktree 使用指南
|
|
146
|
-
|
|
147
|
-
以下场景**必须**使用 `isolation: "worktree"`:
|
|
148
|
-
|
|
149
|
-
- 多个 Agent 各自创建/修改不同文件
|
|
150
|
-
- Agent 的修改可能与当前工作区冲突
|
|
151
|
-
- 需要保持主工作区干净(如正在进行其他工作)
|
|
152
|
-
|
|
153
|
-
以下场景**不需要** worktree:
|
|
154
|
-
|
|
155
|
-
- 纯只读的 Explore Agent
|
|
156
|
-
- 步骤级并行的工具调用(Grep/Glob/Read/Bash)
|
|
157
|
-
- 单个 Agent 执行(无冲突风险)
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# Git Commit 强制规范
|
|
2
|
-
|
|
3
|
-
**每次 `git commit` 前必须完整执行以下检查流程,不可跳过任何步骤。**
|
|
4
|
-
|
|
5
|
-
## 提交前强制检查流程
|
|
6
|
-
|
|
7
|
-
执行 `git commit` 前,按顺序完成以下 4 步。任何一步未通过则 **STOP,不得提交**。
|
|
8
|
-
|
|
9
|
-
### Step 1: 分析变更内容
|
|
10
|
-
|
|
11
|
-
运行 `git diff --cached` 查看暂存区,回答以下问题:
|
|
12
|
-
|
|
13
|
-
- 这次变更做了几件事?
|
|
14
|
-
- 涉及哪些模块/目录?
|
|
15
|
-
|
|
16
|
-
**如果做了多件事** → STOP,必须拆成多个 commit。判断标准:能否用一个 ≤ 72 字符的 subject 清晰描述?不能就必须拆。
|
|
17
|
-
|
|
18
|
-
### Step 2: 确定 scope
|
|
19
|
-
|
|
20
|
-
读取当前项目 CLAUDE.md,查找 `## Git Commit Scope` 段落:
|
|
21
|
-
|
|
22
|
-
- **找到了** → scope 必须从其中定义的枚举值中选取,不得自造
|
|
23
|
-
- **没找到** → 提醒用户:「当前项目 CLAUDE.md 未定义 Git Commit Scope,建议添加。需要我帮你加吗?」,然后 scope 可省略
|
|
24
|
-
|
|
25
|
-
scope 使用规则:
|
|
26
|
-
- 变更仅涉及单个模块 → **必须**带 scope
|
|
27
|
-
- 变更跨多个模块 → 省略 scope
|
|
28
|
-
|
|
29
|
-
### Step 3: 生成 commit message
|
|
30
|
-
|
|
31
|
-
格式必须严格匹配:
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
<type>(<scope>): <subject>
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
或(无 scope 时):
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
<type>: <subject>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**type 只能从以下枚举中选取:**
|
|
44
|
-
|
|
45
|
-
| type | 用途 |
|
|
46
|
-
|------|------|
|
|
47
|
-
| feat | 新功能 |
|
|
48
|
-
| fix | 修复 bug |
|
|
49
|
-
| refactor | 重构(不改变外部行为) |
|
|
50
|
-
| chore | 构建/依赖/配置/发版等杂务 |
|
|
51
|
-
| docs | 文档变更 |
|
|
52
|
-
| test | 测试新增或修改 |
|
|
53
|
-
| perf | 性能优化 |
|
|
54
|
-
| style | 代码格式调整(不影响逻辑) |
|
|
55
|
-
| ci | CI/CD 配置变更 |
|
|
56
|
-
|
|
57
|
-
**subject 强制要求:**
|
|
58
|
-
|
|
59
|
-
- **中文**描述
|
|
60
|
-
- 不加句号
|
|
61
|
-
- ≤ 72 字符
|
|
62
|
-
- 用简洁的动宾短语:`添加`、`修复`、`移除`、`重构`、`升级`
|
|
63
|
-
|
|
64
|
-
**body(可选):**
|
|
65
|
-
|
|
66
|
-
- 空一行后写
|
|
67
|
-
- 中文,只写 why(动机、背景),不复述 what
|
|
68
|
-
- 破坏性变更加 `BREAKING CHANGE:` 前缀
|
|
69
|
-
|
|
70
|
-
### Step 4: 自检验证
|
|
71
|
-
|
|
72
|
-
生成 commit message 后,逐条验证:
|
|
73
|
-
|
|
74
|
-
- [ ] type 在枚举表中?
|
|
75
|
-
- [ ] scope 符合项目 CLAUDE.md 定义(或正确省略)?
|
|
76
|
-
- [ ] subject 是中文、无句号、≤ 72 字符、简洁动宾短语?
|
|
77
|
-
- [ ] 一个 commit 只做一件事,没有混合不同 type 的变更?
|
|
78
|
-
- [ ] 没有混合不同 scope 的独立变更?
|
|
79
|
-
|
|
80
|
-
**全部通过 → 执行 commit。任何一条未通过 → 修正后重新验证。**
|
|
81
|
-
|
|
82
|
-
## 常见错误(必须避免)
|
|
83
|
-
|
|
84
|
-
| 错误 | 正确 |
|
|
85
|
-
|------|------|
|
|
86
|
-
| `feat: add user login`(英文) | `feat: 添加用户登录功能`(中文) |
|
|
87
|
-
| `fix(eui): 修复了按钮样式。` | `fix(eui): 修复按钮样式`(无句号、不用「了」) |
|
|
88
|
-
| `feat: 添加登录功能并修复登出 bug` | 拆成两个 commit |
|
|
89
|
-
| `update: 修改配置` | `update` 不在 type 枚举中,应为 `chore` |
|
|
90
|
-
| `feat(auth): 添加 JWT 刷新`(项目 scope 枚举无 auth) | 使用项目定义的 scope 值 |
|
|
91
|
-
|
|
92
|
-
## 正确示例
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
feat(eui): 添加 Image 组件,支持懒加载
|
|
96
|
-
|
|
97
|
-
fix: 修复 token 刷新竞态条件
|
|
98
|
-
|
|
99
|
-
refactor(backend): 提取分页逻辑为共享工具
|
|
100
|
-
|
|
101
|
-
chore: 升级 Vite 至 8.x
|
|
102
|
-
|
|
103
|
-
feat(eui)!: 重命名 EDialog open 属性为 v-model:open
|
|
104
|
-
|
|
105
|
-
BREAKING CHANGE: EDialog 不再接受 `visible` 属性,请改用 `v-model:open`。
|
|
106
|
-
```
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: git-security
|
|
3
|
-
description: Git 提交安全规则
|
|
4
|
-
type: claude-rule
|
|
5
|
-
tags: [security, git]
|
|
6
|
-
version: 1.0.0
|
|
7
|
-
author: chances
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# Git 提交安全规则
|
|
11
|
-
|
|
12
|
-
每次执行 `git add` 或 `git commit` 前必须遵循以下规则。违反时必须**立即停止并提示用户确认**。
|
|
13
|
-
|
|
14
|
-
## 一、禁止提交的文件
|
|
15
|
-
|
|
16
|
-
### 绝对禁止(无论任何理由)
|
|
17
|
-
以下文件**永远不得**被 `git add`:
|
|
18
|
-
|
|
19
|
-
| 文件类型 | 示例 |
|
|
20
|
-
|---|---|
|
|
21
|
-
| 环境变量文件 | `.env`、`.env.local`、`.env.production`、`*.env` |
|
|
22
|
-
| SSH 密钥 | `id_rsa`、`id_ed25519`、`*.pem`、`*.key` |
|
|
23
|
-
| 证书文件 | `*.p12`、`*.pfx`、`*.jks`、`*.keystore` |
|
|
24
|
-
| 数据库文件 | `*.sql`(含真实数据的)、`*.dump`、`*.sqlite` |
|
|
25
|
-
| 原始数据 | `*.xlsx`、`*.csv`(含用户/学生等敏感数据的) |
|
|
26
|
-
| 日志文件 | `*.log` |
|
|
27
|
-
| Docker 卷数据 | `pgdata/`、`cache/*.json` |
|
|
28
|
-
|
|
29
|
-
### 检测方法
|
|
30
|
-
在执行 `git add` 前,检查暂存区是否包含上述文件:
|
|
31
|
-
```bash
|
|
32
|
-
git diff --cached --name-only | grep -iE '\.(env|pem|key|p12|pfx|jks|dump|sqlite|log)$'
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## 二、禁止提交的内容
|
|
36
|
-
|
|
37
|
-
### 总则:所有示例必须使用假值
|
|
38
|
-
**禁止在代码、文档、规则文件、注释中出现任何真实的 API Key、Token、密码、IP 地址等敏感信息,即使是作为"示例"也不允许。** 所有示例必须使用明显的假值/脱敏值(如 `sk-xxxxxxxxxxxx`、`your-key-here`、`192.168.x.x`)。GitHub Secret Scanning 不区分上下文,真实格式的 key 即使写在文档示例中也会触发泄露告警。
|
|
39
|
-
|
|
40
|
-
### 必须扫描的敏感模式
|
|
41
|
-
对每个将要提交的文件内容,检查是否包含以下模式:
|
|
42
|
-
|
|
43
|
-
| 类型 | 匹配模式 | 示例(均为假值) |
|
|
44
|
-
|---|---|---|
|
|
45
|
-
| API Key | `sk-[a-zA-Z0-9]{20,}` | `sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx` |
|
|
46
|
-
| AWS Key | `AKIA[0-9A-Z]{16}` | `AKIAIOSFODNN7EXAMPLE` |
|
|
47
|
-
| 密码赋值 | `password\s*[:=]\s*["'][^"']{4,}` | `password = "abc123"` |
|
|
48
|
-
| 数据库连接串 | `://\w+:[^@\s]+@` | `postgresql://user:pass@host` |
|
|
49
|
-
| 私钥内容 | `-----BEGIN (RSA |EC )?PRIVATE KEY-----` | PEM 私钥 |
|
|
50
|
-
| Token | `token\s*[:=]\s*["'][a-zA-Z0-9_\-]{20,}` | `token = "ghp_xxxx"` |
|
|
51
|
-
| Secret | `secret\s*[:=]\s*["'][^"']{8,}` | `secret = "my-secret"` |
|
|
52
|
-
| 服务器 IP+端口 | `\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+` | `192.168.1.1:8080` |
|
|
53
|
-
| SSH 连接 | `ssh\s+.*@\d{1,3}\.\d{1,3}` | `ssh user@192.168.1.1` |
|
|
54
|
-
|
|
55
|
-
### 例外:允许的模式
|
|
56
|
-
以下情况**不算**违规:
|
|
57
|
-
- `.env.example` 中的占位符(如 `DEEPSEEK_API_KEY=your-key-here`)
|
|
58
|
-
- 代码中从环境变量读取的引用(如 `os.getenv("API_KEY")`)
|
|
59
|
-
- `localhost` 或 `127.0.0.1` 的连接串
|
|
60
|
-
- 文档中的示例/假数据(如 `sk-xxxxxxxxxxxx`)
|
|
61
|
-
- 配置文件中的空字符串默认值(如 `api_key: str = ""`)
|
|
62
|
-
|
|
63
|
-
## 三、提交前检查流程
|
|
64
|
-
|
|
65
|
-
每次 `git commit` 前必须执行:
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
1. 检查暂存文件列表 → 是否包含禁止文件类型?
|
|
69
|
-
2. 检查文件内容差异 → 是否包含敏感模式?
|
|
70
|
-
3. 检查 .gitignore → 是否已排除敏感目录?
|
|
71
|
-
4. 通过 → 执行提交
|
|
72
|
-
5. 未通过 → 停止,提示用户具体违规项
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 自动检查命令
|
|
76
|
-
```bash
|
|
77
|
-
# 检查暂存区的敏感文件
|
|
78
|
-
git diff --cached --name-only | grep -iE '\.(env|pem|key|log|dump|sqlite)$'
|
|
79
|
-
|
|
80
|
-
# 检查暂存区内容中的敏感信息
|
|
81
|
-
git diff --cached -U0 | grep -iE '(sk-[a-zA-Z0-9]{20}|AKIA[0-9A-Z]{16}|-----BEGIN.*PRIVATE KEY|password\s*[:=]\s*"[^"]{4,}"|://\w+:[^@\s]+@[^l])'
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## 四、.gitignore 最低要求
|
|
85
|
-
|
|
86
|
-
每个项目的 `.gitignore` 必须至少包含:
|
|
87
|
-
|
|
88
|
-
```gitignore
|
|
89
|
-
# 环境变量
|
|
90
|
-
.env
|
|
91
|
-
*.env
|
|
92
|
-
.env.*
|
|
93
|
-
|
|
94
|
-
# 密钥
|
|
95
|
-
*.pem
|
|
96
|
-
*.key
|
|
97
|
-
*.p12
|
|
98
|
-
|
|
99
|
-
# 缓存与编译
|
|
100
|
-
__pycache__/
|
|
101
|
-
*.pyc
|
|
102
|
-
node_modules/
|
|
103
|
-
dist/
|
|
104
|
-
|
|
105
|
-
# 日志
|
|
106
|
-
*.log
|
|
107
|
-
|
|
108
|
-
# 数据库
|
|
109
|
-
*.sqlite
|
|
110
|
-
*.dump
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
如果项目的 `.gitignore` 缺少以上条目,提交前必须先补全。
|
|
114
|
-
|
|
115
|
-
## 五、已提交敏感数据的处理
|
|
116
|
-
|
|
117
|
-
如果发现敏感数据已存在于 git 历史中:
|
|
118
|
-
|
|
119
|
-
1. **立即通知用户**,说明哪些数据已泄露
|
|
120
|
-
2. **建议轮换凭证**(API Key、密码等)
|
|
121
|
-
3. **提供清理命令**(但不自动执行,等用户确认):
|
|
122
|
-
```bash
|
|
123
|
-
# 从所有历史中删除文件
|
|
124
|
-
git filter-repo --path <file> --invert-paths --force
|
|
125
|
-
|
|
126
|
-
# 或使用 BFG
|
|
127
|
-
bfg --delete-files <filename>
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## 六、违规处理流程
|
|
131
|
-
|
|
132
|
-
当检测到提交操作包含敏感数据时:
|
|
133
|
-
|
|
134
|
-
1. **立即停止** `git add` 或 `git commit`
|
|
135
|
-
2. **列出具体违规项**:
|
|
136
|
-
- 文件名和行号
|
|
137
|
-
- 匹配到的敏感模式类型
|
|
138
|
-
- 敏感内容的部分摘要(如 `sk-5522****dc3`,脱敏显示)
|
|
139
|
-
3. **提供建议**:
|
|
140
|
-
- 将文件加入 `.gitignore`
|
|
141
|
-
- 将敏感值移到 `.env`
|
|
142
|
-
- 使用环境变量替代硬编码
|
|
143
|
-
4. **等待用户明确确认**后才能继续
|
|
144
|
-
5. 如用户确认提交,添加注释:`# GIT-SECURITY: 用户已确认提交此内容`
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dwy-backend-base
|
|
3
|
-
description: "danweiyuan-base FastAPI 后端基础设施速查。触发条件:使用 FastAPI 构建后端、配置数据库/Redis/JWT/异常处理时。"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# danweiyuan-base 后端基础设施速查
|
|
7
|
-
|
|
8
|
-
FastAPI 项目基础设施包,Python 3.11+,全异步。8 个扁平模块,无子包。
|
|
9
|
-
|
|
10
|
-
## 安装
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
pip install danweiyuan-base
|
|
14
|
-
# 或
|
|
15
|
-
uv add danweiyuan-base
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
```python
|
|
19
|
-
from danweiyuan_base.config import BaseSettings
|
|
20
|
-
from danweiyuan_base.database import Base, TimestampMixin, create_async_engine_factory, create_session_factory
|
|
21
|
-
from danweiyuan_base.security import hash_password, verify_password, create_token, decode_token
|
|
22
|
-
from danweiyuan_base.exceptions import NotFoundError, BusinessError, register_exception_handlers
|
|
23
|
-
from danweiyuan_base.response import success, fail, paginated
|
|
24
|
-
from danweiyuan_base.pagination import PaginationParams, paginate
|
|
25
|
-
from danweiyuan_base.cache import configure as configure_redis, get_redis, close_redis
|
|
26
|
-
from danweiyuan_base.dependencies import create_get_db
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## 查阅源码
|
|
30
|
-
|
|
31
|
-
每个模块在 `backend/src/danweiyuan_base/{module}.py`,单文件设计可直接阅读。
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## config — Pydantic Settings
|
|
36
|
-
|
|
37
|
-
```python
|
|
38
|
-
from danweiyuan_base.config import BaseSettings
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
子类化后使用,从 `.env` 或环境变量读取配置。
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
class Settings(BaseSettings):
|
|
45
|
-
app_name: str = "My API"
|
|
46
|
-
# 继承的必填字段:database_url, redis_url, secret_key
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
| 字段 | 类型 | 默认值 | 说明 |
|
|
50
|
-
|------|------|--------|------|
|
|
51
|
-
| database_url | str | **必填** | 异步数据库 URL |
|
|
52
|
-
| redis_url | str | **必填** | Redis URL |
|
|
53
|
-
| secret_key | str | **必填** | JWT 签名密钥 |
|
|
54
|
-
| jwt_algorithm | str | `"HS256"` | JWT 算法 |
|
|
55
|
-
| access_token_expire_minutes | int | `30` | Token 过期分钟 |
|
|
56
|
-
| debug | bool | `False` | 调试模式 |
|
|
57
|
-
| allowed_origins | list[str] | `[]` | CORS 允许域名 |
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## database — 异步 SQLAlchemy
|
|
62
|
-
|
|
63
|
-
```python
|
|
64
|
-
from danweiyuan_base.database import Base, TimestampMixin, create_async_engine_factory, create_session_factory
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 模型定义
|
|
68
|
-
|
|
69
|
-
```python
|
|
70
|
-
from sqlalchemy.orm import Mapped, mapped_column
|
|
71
|
-
from sqlalchemy import String
|
|
72
|
-
|
|
73
|
-
class User(Base, TimestampMixin):
|
|
74
|
-
__tablename__ = "users"
|
|
75
|
-
id: Mapped[int] = mapped_column(primary_key=True)
|
|
76
|
-
name: Mapped[str] = mapped_column(String(50))
|
|
77
|
-
# TimestampMixin 自动添加 created_at, updated_at
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 引擎和会话
|
|
81
|
-
|
|
82
|
-
```python
|
|
83
|
-
engine = create_async_engine_factory(settings.database_url, echo=settings.debug)
|
|
84
|
-
# 参数: database_url, pool_size=5, max_overflow=10, echo=False
|
|
85
|
-
# SQLite 自动跳过连接池参数
|
|
86
|
-
|
|
87
|
-
session_factory = create_session_factory(engine)
|
|
88
|
-
# 返回 async_sessionmaker[AsyncSession],expire_on_commit=False
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## dependencies — FastAPI 依赖注入
|
|
94
|
-
|
|
95
|
-
```python
|
|
96
|
-
from danweiyuan_base.dependencies import create_get_db
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### create_get_db(session_factory)
|
|
100
|
-
|
|
101
|
-
生成 `get_db` FastAPI Depends 函数,自动管理会话生命周期。
|
|
102
|
-
|
|
103
|
-
```python
|
|
104
|
-
get_db = create_get_db(session_factory)
|
|
105
|
-
|
|
106
|
-
@router.get("/users/{user_id}")
|
|
107
|
-
async def get_user(user_id: int, db: AsyncSession = Depends(get_db)):
|
|
108
|
-
...
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## security — JWT + bcrypt
|
|
114
|
-
|
|
115
|
-
```python
|
|
116
|
-
from danweiyuan_base.security import hash_password, verify_password, create_token, decode_token
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
所有函数无状态,密钥通过参数传入。
|
|
120
|
-
|
|
121
|
-
| 函数 | 签名 | 说明 |
|
|
122
|
-
|------|------|------|
|
|
123
|
-
| hash_password | `(password: str) -> str` | bcrypt 哈希 |
|
|
124
|
-
| verify_password | `(plain: str, hashed: str) -> bool` | 验证密码 |
|
|
125
|
-
| create_token | `(data: dict, secret: str, expires_minutes: int, algorithm="HS256") -> str` | 创建 JWT,自动添加 exp |
|
|
126
|
-
| decode_token | `(token: str, secret: str, algorithm="HS256") -> dict \| None` | 解码 JWT,失败返回 None |
|
|
127
|
-
|
|
128
|
-
```python
|
|
129
|
-
hashed = hash_password("my-password")
|
|
130
|
-
is_valid = verify_password("my-password", hashed)
|
|
131
|
-
|
|
132
|
-
token = create_token({"sub": str(user.id)}, settings.secret_key, settings.access_token_expire_minutes)
|
|
133
|
-
payload = decode_token(token, settings.secret_key) # {"sub": "1", "exp": ...} 或 None
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## exceptions — 异常体系
|
|
139
|
-
|
|
140
|
-
```python
|
|
141
|
-
from danweiyuan_base.exceptions import (
|
|
142
|
-
AppError, NotFoundError, BusinessError, PermissionDeniedError, AuthenticationError,
|
|
143
|
-
register_exception_handlers,
|
|
144
|
-
)
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
### 异常层级
|
|
148
|
-
|
|
149
|
-
| 异常类 | HTTP 状态码 | code | message |
|
|
150
|
-
|--------|-----------|------|---------|
|
|
151
|
-
| AppError(message, code) | — | 自定义 | 自定义 |
|
|
152
|
-
| NotFoundError(resource) | 404 | `NOT_FOUND` | `{resource}不存在` |
|
|
153
|
-
| BusinessError(message, code) | 422 | 自定义 | 自定义 |
|
|
154
|
-
| PermissionDeniedError() | 403 | `PERMISSION_DENIED` | `权限不足` |
|
|
155
|
-
| AuthenticationError() | 401 | `AUTHENTICATION_FAILED` | `认证失败` |
|
|
156
|
-
|
|
157
|
-
### 注册到 FastAPI
|
|
158
|
-
|
|
159
|
-
```python
|
|
160
|
-
app = FastAPI()
|
|
161
|
-
register_exception_handlers(app)
|
|
162
|
-
# 之后在 service 层直接 raise NotFoundError("用户") 即可返回 404
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
响应格式统一为 `{"code": "ERROR_CODE", "message": "描述"}`。
|
|
166
|
-
|
|
167
|
-
### 使用原则
|
|
168
|
-
|
|
169
|
-
- **service 层**抛业务异常(NotFoundError, BusinessError 等)
|
|
170
|
-
- **router 层**不写 try/except,由 register_exception_handlers 统一处理
|
|
171
|
-
- **禁止**在 service 层抛 HTTPException
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
## response — 统一响应
|
|
176
|
-
|
|
177
|
-
```python
|
|
178
|
-
from danweiyuan_base.response import success, fail, paginated
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
| 函数 | 签名 | 返回结构 |
|
|
182
|
-
|------|------|---------|
|
|
183
|
-
| success | `(data=None, message="success") -> dict` | `{"code": 200, "message": ..., "data": ..., "timestamp": ...}` |
|
|
184
|
-
| fail | `(code=400, message="fail") -> dict` | `{"code": ..., "message": ..., "data": None, "timestamp": ...}` |
|
|
185
|
-
| paginated | `(items, total, page, page_size) -> dict` | success 包装 `{"items": [...], "total": N, "page": N, "page_size": N}` |
|
|
186
|
-
|
|
187
|
-
```python
|
|
188
|
-
@router.get("/users/{user_id}")
|
|
189
|
-
async def get_user(user_id: int, service=Depends(get_user_service)):
|
|
190
|
-
user = await service.get_by_id(user_id)
|
|
191
|
-
return success(data=UserResponse.model_validate(user))
|
|
192
|
-
|
|
193
|
-
@router.get("/users")
|
|
194
|
-
async def list_users(params: PaginationParams = Depends(), service=Depends(get_user_service)):
|
|
195
|
-
items, total = await service.list(params)
|
|
196
|
-
return paginated(items, total, params.page, params.page_size)
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## pagination — 分页工具
|
|
202
|
-
|
|
203
|
-
```python
|
|
204
|
-
from danweiyuan_base.pagination import PaginationParams, paginate, OffsetLimit
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### PaginationParams
|
|
208
|
-
|
|
209
|
-
FastAPI Depends 注入的查询参数模型。
|
|
210
|
-
|
|
211
|
-
| 字段 | 类型 | 默认 | 约束 |
|
|
212
|
-
|------|------|------|------|
|
|
213
|
-
| page | int | 1 | >= 1 |
|
|
214
|
-
| page_size | int | 20 | 1 ~ 100 |
|
|
215
|
-
|
|
216
|
-
### paginate(page, page_size) -> OffsetLimit
|
|
217
|
-
|
|
218
|
-
```python
|
|
219
|
-
offset_limit = paginate(params.page, params.page_size)
|
|
220
|
-
# OffsetLimit(offset=0, limit=20) — 可直接用于 SQLAlchemy .offset().limit()
|
|
221
|
-
stmt = select(User).offset(offset_limit.offset).limit(offset_limit.limit)
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## cache — 异步 Redis
|
|
227
|
-
|
|
228
|
-
```python
|
|
229
|
-
from danweiyuan_base import cache
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
| 函数 | 签名 | 说明 |
|
|
233
|
-
|------|------|------|
|
|
234
|
-
| cache.configure | `(redis_url: str) -> None` | 设置 Redis URL(启动时调用一次) |
|
|
235
|
-
| cache.get_redis | `async () -> Redis` | 获取/创建共享连接(未 configure 时抛 RuntimeError) |
|
|
236
|
-
| cache.close_redis | `async () -> None` | 关闭连接(安全幂等) |
|
|
237
|
-
|
|
238
|
-
```python
|
|
239
|
-
# lifespan 中初始化
|
|
240
|
-
@asynccontextmanager
|
|
241
|
-
async def lifespan(app: FastAPI):
|
|
242
|
-
cache.configure(settings.redis_url)
|
|
243
|
-
yield
|
|
244
|
-
await cache.close_redis()
|
|
245
|
-
|
|
246
|
-
# 业务中使用
|
|
247
|
-
redis = await cache.get_redis()
|
|
248
|
-
await redis.set("key", "value", ex=3600)
|
|
249
|
-
val = await redis.get("key")
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## 典型项目接入流程
|
|
255
|
-
|
|
256
|
-
```python
|
|
257
|
-
# config.py
|
|
258
|
-
from danweiyuan_base.config import BaseSettings
|
|
259
|
-
|
|
260
|
-
class Settings(BaseSettings):
|
|
261
|
-
app_name: str = "My API"
|
|
262
|
-
|
|
263
|
-
settings = Settings()
|
|
264
|
-
|
|
265
|
-
# database.py
|
|
266
|
-
from danweiyuan_base.database import Base, create_async_engine_factory, create_session_factory
|
|
267
|
-
from danweiyuan_base.dependencies import create_get_db
|
|
268
|
-
|
|
269
|
-
engine = create_async_engine_factory(settings.database_url)
|
|
270
|
-
session_factory = create_session_factory(engine)
|
|
271
|
-
get_db = create_get_db(session_factory)
|
|
272
|
-
|
|
273
|
-
# main.py
|
|
274
|
-
from danweiyuan_base.exceptions import register_exception_handlers
|
|
275
|
-
from danweiyuan_base import cache
|
|
276
|
-
|
|
277
|
-
app = FastAPI(lifespan=lifespan)
|
|
278
|
-
register_exception_handlers(app)
|
|
279
|
-
```
|