hookehuyr

feat(claude): 添加API生成器技能并更新Claude配置

添加完整的API生成器技能,包括从OpenAPI文档生成前端API代码的工具链
更新Claude配置以支持pnpm包管理器和MCP服务器
重构权限设置,优化开发工具链集成
1 -# API Diff Skill
2 -
3 -对比两个版本的 OpenAPI 文档或生成的 API 文件,检测接口变更。
4 -
5 -## 使用场景
6 -
7 -1. **更新 API 后自动检查**:运行 `api:generate` 后自动对比新旧接口
8 -2. **手动对比**:对比两个不同的 OpenAPI 文档
9 -3. **CI/CD 集成**:在部署前检查破坏性 API 变更
10 -
11 -## 如何调用
12 -
13 -### 在生成 API 后自动对比
14 -```bash
15 -pnpm run api:generate
16 -```
17 -生成器会自动调用对比逻辑,检查是否有接口变更。
18 -
19 -### 手动对比两个文档
20 -```bash
21 -# 对比两个 OpenAPI markdown 文档
22 -node scripts/apiDiff.js docs/api-specs/user/api1.md docs/api-specs/user/api1-new.md
23 -
24 -# 对比整个模块目录
25 -node scripts/apiDiff.js docs/api-specs/user/ docs/api-specs/user-new/
26 -
27 -# 对比生成的 API 文件
28 -node scripts/apiDiff.js src/api/user.js src/api/user-new.js
29 -```
30 -
31 -## 对比维度
32 -
33 -1. **接口增删**:新增或删除的接口
34 -2. **参数变更**
35 - - 新增必填参数(破坏性变更)
36 - - 删除参数(破坏性变更)
37 - - 参数类型变更(破坏性变更)
38 - - 新增可选参数(非破坏性)
39 -3. **返回值变更**
40 - - 返回结构变更
41 - - 字段类型变更
42 -4. **HTTP 方法变更**:GET ↔ POST(破坏性变更)
43 -
44 -## 输出格式
45 -
46 -对比结果会以以下格式输出:
47 -
48 -```
49 -=== API 变更检测报告 ===
50 -
51 -📦 模块: user
52 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
53 -
54 -✅ 新增接口 (1):
55 - + getUserProfile
56 -
57 -⚠️ 修改接口 (2):
58 - ↪ editUserInfo
59 - ✗ [破坏性] 删除必填参数: sms_code
60 - ✓ [非破坏性] 新增可选参数: avatar
61 -
62 - ↪ getUserInfo
63 - ✓ [非破坏性] 新增可选参数: include_profile
64 -
65 -❌ 删除接口 (1):
66 - - deleteUserAccount
67 -
68 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
69 -总计: 1 新增, 2 修改, 1 删除
70 -⚠️ 检测到 1 个破坏性变更,请仔细检查业务逻辑!
71 -```
72 -
73 -## 退出码
74 -
75 -- `0`: 无变更或仅有非破坏性变更
76 -- `1`: 检测到破坏性变更(可用于 CI/CD 失败)
77 -
78 -## 配置选项
79 -
80 -可以通过环境变量配置:
81 -
82 -```bash
83 -# 严格模式:任何变更都返回失败码
84 -API_DIFF_STRICT=true node scripts/apiDiff.js ...
85 -
86 -# 输出 JSON 格式(用于程序解析)
87 -API_DIFF_FORMAT=json node scripts/apiDiff.js ...
88 -```
89 -
90 -## 注意事项
91 -
92 -1. 对比逻辑基于 OpenAPI 规范,确保文档格式正确
93 -2. 破坏性变更需要在业务代码中做兼容处理
94 -3. 新增接口通常不需要修改现有代码
95 -4. 删除接口前请确认没有地方在使用
This diff is collapsed. Click to expand it.
1 +#!/bin/bash
2 +
3 +# API Generator Skill 安装脚本
4 +# 用于将 API Generator 功能安装到当前项目
5 +
6 +set -e
7 +
8 +echo "🚀 API Generator Skill 安装程序"
9 +echo "================================"
10 +echo ""
11 +
12 +# 颜色定义
13 +GREEN='\033[0;32m'
14 +YELLOW='\033[1;33m'
15 +RED='\033[0;31m'
16 +NC='\033[0m' # No Color
17 +
18 +# 检查是否在项目根目录
19 +if [ ! -f "package.json" ]; then
20 + echo -e "${RED}❌ 错误: 请在项目根目录运行此脚本${NC}"
21 + exit 1
22 +fi
23 +
24 +# 检查 package.json 中是否已有 api:generate 命令
25 +if grep -q '"api:generate"' package.json; then
26 + echo -e "${YELLOW}⚠️ 检测到已存在 api:generate 命令${NC}"
27 + read -p "是否覆盖? (y/N) " -n 1 -r
28 + echo
29 + if [[ ! $REPLY =~ ^[Yy]$ ]]; then
30 + echo "安装已取消"
31 + exit 0
32 + fi
33 +fi
34 +
35 +# 创建目录结构
36 +echo -e "${GREEN}📁 创建目录结构...${NC}"
37 +mkdir -p .claude/custom_skills/api-generator/{scripts,templates,setup}
38 +mkdir -p docs/openAPI
39 +mkdir -p .tmp
40 +
41 +# 检查必要的文件
42 +echo -e "${GREEN}📋 检查文件...${NC}"
43 +
44 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
45 +
46 +# 检查脚本文件
47 +if [ ! -f "$SCRIPT_DIR/../scripts/generateApiFromOpenAPI.js" ]; then
48 + echo -e "${RED}❌ 缺少 generateApiFromOpenAPI.js${NC}"
49 + exit 1
50 +fi
51 +
52 +if [ ! -f "$SCRIPT_DIR/../scripts/apiDiff.js" ]; then
53 + echo -e "${RED}❌ 缺少 apiDiff.js${NC}"
54 + exit 1
55 +fi
56 +
57 +# 检查模板文件
58 +if [ ! -f "$SCRIPT_DIR/../templates/openAPI-template.md" ]; then
59 + echo -e "${RED}❌ 缺少 openAPI-template.md${NC}"
60 + exit 1
61 +fi
62 +
63 +# 安装依赖
64 +echo -e "${GREEN}📦 检查依赖...${NC}"
65 +
66 +if ! command -v pnpm &> /dev/null; then
67 + echo -e "${YELLOW}⚠️ pnpm 未安装,尝试使用 npm...${NC}"
68 + PKG_MANAGER="npm"
69 +else
70 + PKG_MANAGER="pnpm"
71 +fi
72 +
73 +# 检查 js-yaml 是否已安装
74 +if ! $PKG_MANAGER list js-yaml &> /dev/null; then
75 + echo -e "${GREEN}📦 安装 js-yaml...${NC}"
76 + $PKG_MANAGER add -D js-yaml
77 +else
78 + echo -e "${GREEN}✅ js-yaml 已安装${NC}"
79 +fi
80 +
81 +# 添加 npm scripts
82 +echo -e "${GREEN}🔧 配置 npm scripts...${NC}"
83 +
84 +# 使用 jq 或临时文件添加 scripts
85 +if command -v jq &> /dev/null; then
86 + jq '.scripts."api:generate" = "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js" |
87 + .scripts."api:diff" = "node .claude/custom_skills/api-generator/scripts/apiDiff.js"' package.json > package.json.tmp
88 + mv package.json.tmp package.json
89 +else
90 + # 使用 sed 添加(更兼容)
91 + if ! grep -q '"api:generate"' package.json; then
92 + # 找到 "scripts" 行并在后面插入
93 + sed -i '' '/"scripts":/a\
94 +\ "api:generate": "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js",\
95 +\ "api:diff": "node .claude/custom_skills/api-generator/scripts/apiDiff.js",
96 +' package.json 2>/dev/null || sed -i '/"scripts":/a\
97 +\ "api:generate": "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js",\
98 +\ "api:diff": "node .claude/custom_skills/api-generator/scripts/apiDiff.js",
99 +' package.json
100 + fi
101 +fi
102 +
103 +# 创建示例文档
104 +echo -e "${GREEN}📝 创建示例文档...${NC}"
105 +mkdir -p docs/openAPI/example
106 +cat > docs/openAPI/example/getExample.md << 'EOF'
107 +# 获取示例数据
108 +
109 +## OpenAPI Specification
110 +
111 +```yaml
112 +openapi: 3.0.1
113 +info:
114 + title: ''
115 + version: 1.0.0
116 +paths:
117 + /srv/:
118 + get:
119 + summary: 获取示例数据
120 + description: 这是一个示例接口,展示如何编写 OpenAPI 文档
121 + tags:
122 + - 示例模块
123 + parameters:
124 + - name: a
125 + in: query
126 + description: action 参数
127 + required: false
128 + example: example_data
129 + schema:
130 + type: string
131 + - name: id
132 + in: query
133 + description: 数据ID
134 + required: true
135 + example: 123
136 + schema:
137 + type: integer
138 + responses:
139 + '200':
140 + description: 成功返回
141 + content:
142 + application/json:
143 + schema:
144 + type: object
145 + properties:
146 + code:
147 + type: integer
148 + description: 0=失败,1=成功
149 + msg:
150 + type: string
151 + description: 错误信息
152 + data:
153 + type: object
154 + properties:
155 + id:
156 + type: integer
157 + description: 数据ID
158 + name:
159 + type: string
160 + description: 名称
161 + created_at:
162 + type: string
163 + description: 创建时间
164 +```
165 +EOF
166 +
167 +# 创建 README
168 +cat > docs/openAPI/README.md << 'EOF'
169 +# OpenAPI 文档目录
170 +
171 +本目录用于存放 OpenAPI 规范的接口文档,这些文档将自动转换为前端 API 调用代码。
172 +
173 +## 目录结构
174 +
175 +```
176 +docs/openAPI/
177 +├── example/ # 示例模块
178 +│ └── getExample.md # 示例接口
179 +├── user/ # 用户模块(你的模块)
180 +├── course/ # 课程模块(你的模块)
181 +└── order/ # 订单模块(你的模块)
182 +```
183 +
184 +## 如何添加新接口
185 +
186 +1. **创建模块目录**(如果不存在)
187 + ```bash
188 + mkdir -p docs/openAPI/yourModule
189 + ```
190 +
191 +2. **创建接口文档**
192 + ```bash
193 + # 使用模板创建
194 + cp .claude/custom_skills/api-generator/templates/openAPI-template.md \
195 + docs/openAPI/yourModule/yourApiName.md
196 + ```
197 +
198 +3. **编辑文档**
199 + - 按照模板填写接口信息
200 + - 遵循 OpenAPI 3.0.1 规范
201 + - 添加详细的参数说明和返回值结构
202 +
203 +4. **生成代码**
204 + ```bash
205 + pnpm api:generate
206 + ```
207 +
208 +5. **使用生成的 API**
209 + ```javascript
210 + import { yourApiNameAPI } from '@/api/yourModule'
211 + ```
212 +
213 +## 命令速查
214 +
215 +```bash
216 +# 生成 API 代码
217 +pnpm api:generate
218 +
219 +# 对比 API 变更
220 +pnpm api:diff docs/openAPI/user/ docs/openAPI/user-new/
221 +
222 +# 查看帮助
223 +cat .claude/custom_skills/api-generator/skill.md
224 +```
225 +
226 +## 注意事项
227 +
228 +- 第一级目录名 = 模块名(会生成 `模块名.js`)
229 +- 第二级文件名 = 接口名(会生成 `接口名API` 函数)
230 +- 所有 `.md` 文件必须包含 YAML 代码块
231 +- 遵循 OpenAPI 3.0.1 规范编写 YAML
232 +
233 +## 参考文档
234 +
235 +详细使用说明请参考:[API Generator Skill 文档](../../.claude/custom_skills/api-generator/skill.md)
236 +EOF
237 +
238 +# 完成
239 +echo ""
240 +echo -e "${GREEN}✅ 安装完成!${NC}"
241 +echo ""
242 +echo "📚 下一步:"
243 +echo " 1. 查看示例文档: cat docs/openAPI/example/getExample.md"
244 +echo " 2. 创建你的第一个接口: cp docs/openAPI/example/getExample.md docs/openAPI/yourModule/yourApi.md"
245 +echo " 3. 生成 API 代码: pnpm api:generate"
246 +echo ""
247 +echo "📖 完整文档: cat .claude/custom_skills/api-generator/skill.md"
248 +echo ""
This diff is collapsed. Click to expand it.
1 +# 接口名称
2 +
3 +## 接口描述
4 +
5 +详细描述这个接口的功能、使用场景和注意事项。
6 +
7 +## OpenAPI Specification
8 +
9 +```yaml
10 +openapi: 3.0.1
11 +info:
12 + title: ''
13 + version: 1.0.0
14 +paths:
15 + /srv/:
16 + get: # 或 post
17 + summary: 接口简介(一行描述)
18 + description: |
19 + 接口详细说明...
20 + - 使用场景 1
21 + - 使用场景 2
22 + tags:
23 + - 模块名称
24 + parameters: # GET 请求使用 parameters
25 + - name: a
26 + in: query
27 + description: action 参数
28 + required: false
29 + example: your_action_name
30 + schema:
31 + type: string
32 + - name: f
33 + in: query
34 + description: 业务模块
35 + required: false
36 + example: behalo
37 + schema:
38 + type: string
39 + - name: id
40 + in: query
41 + description: 参数描述
42 + required: true # true=必填,false=可选
43 + example: 123
44 + schema:
45 + type: integer
46 + requestBody: # POST 请求使用 requestBody
47 + content:
48 + application/x-www-form-urlencoded: # 或 application/json
49 + schema:
50 + type: object
51 + required:
52 + - course_id
53 + - quantity
54 + properties:
55 + course_id:
56 + type: integer
57 + description: 课程ID
58 + example: 1
59 + quantity:
60 + type: integer
61 + description: 数量
62 + example: 1
63 + responses:
64 + '200':
65 + description: 成功返回
66 + content:
67 + application/json:
68 + schema:
69 + type: object
70 + properties:
71 + code:
72 + type: integer
73 + description: 0=失败,1=成功
74 + msg:
75 + type: string
76 + description: 错误信息
77 + data:
78 + type: object
79 + description: 返回数据
80 + properties:
81 + id:
82 + type: integer
83 + description: 数据ID
84 + name:
85 + type: string
86 + description: 名称
87 + items:
88 + type: array
89 + description: 列表数据
90 + items:
91 + type: object
92 + properties:
93 + item_id:
94 + type: integer
95 + description: 项目ID
96 + item_name:
97 + type: string
98 + description: 项目名称
99 +```
100 +
101 +## 使用示例
102 +
103 +### GET 请求示例
104 +
105 +```javascript
106 +import { getYourAPINameAPI } from '@/api/yourModule'
107 +
108 +const { code, data } = await getYourAPINameAPI({
109 + id: 123,
110 + page: 1,
111 + limit: 10
112 +})
113 +
114 +if (code === 1) {
115 + console.log('成功:', data)
116 +}
117 +```
118 +
119 +### POST 请求示例
120 +
121 +```javascript
122 +import { createYourResourceAPI } from '@/api/yourModule'
123 +
124 +const { code, data } = await createYourResourceAPI({
125 + course_id: 1,
126 + quantity: 2
127 +})
128 +
129 +if (code === 1) {
130 + console.log('创建成功:', data)
131 +}
132 +```
133 +
134 +## 注意事项
135 +
136 +- **权限要求**: 说明是否需要登录、特殊权限等
137 +- **限流规则**: 说明接口调用频率限制
138 +- **错误码**: 列出常见的错误码及含义
139 +- **兼容性**: 说明版本兼容性要求
140 +
141 +## 相关接口
142 +
143 +- [相关接口1](./relatedApi1.md)
144 +- [相关接口2](./relatedApi2.md)
145 +
146 +## 更新记录
147 +
148 +- **2026-01-29**: 初始版本,创建接口
1 +{
2 + "packageManager": "pnpm"
3 +}
1 +{
2 + "mcpServers": {
3 + "mlaj_API_文档": {
4 + "command": "npx",
5 + "args": [
6 + "-y",
7 + "apifox-mcp-server@latest",
8 + "--project-id=6084040"
9 + ],
10 + "env": {
11 + "APIFOX_ACCESS_TOKEN": "APS-jkT1Q61MCKgzgvfCL2euIR2TcgKsnSyc"
12 + }
13 + }
14 + }
15 +}
1 { 1 {
2 "permissions": { 2 "permissions": {
3 "allow": [ 3 "allow": [
4 - "Bash(pandoc:*)",
5 - "Bash(npx skills --help:*)",
6 - "Bash(pnpm add:*)",
7 - "Bash(pnpm api:generate:*)",
8 - "Bash(node:*)",
9 - "Bash(ls:*)",
10 "Bash(tree:*)", 4 "Bash(tree:*)",
11 - "Bash(git checkout:*)", 5 + "Bash(xargs awk:*)",
6 + "Bash(find:*)",
7 + "Bash(grep:*)",
8 + "Bash(git diff:*)",
9 + "mcp__web-search-prime__webSearchPrime",
10 + "mcp__web-reader__webReader",
11 + "Bash(ls:*)",
12 + "Bash(for:*)",
13 + "Bash(do if [ -f \"$dirskill.md\" ])",
14 + "Bash(fi:*)",
15 + "Bash(done:*)",
16 + "Bash(if:*)",
17 + "Bash(then echo \"找到项目本地技能:\")",
18 + "Bash(else echo \"当前项目没有本地技能目录\")",
19 + "Bash(command:*)",
20 + "Bash(then mv \"$dirskill.md\" \"$dirSKILL.md\")",
21 + "Bash(do if [ -f \"$dirSKILL.md\" ])",
22 + "Bash(then rmdir ~/.config/claude-code/skills)",
23 + "Bash(else echo \"目录不为空或不存在,跳过删除\")",
24 + "Bash(chmod:*)",
25 + "Bash(scripts/upload-to-qiniu.sh:*)",
26 + "Bash(curl:*)",
12 "Bash(git add:*)", 27 "Bash(git add:*)",
13 "Bash(git commit:*)", 28 "Bash(git commit:*)",
29 + "Bash(git push)",
30 + "Bash(git restore:*)",
31 + "Bash(pnpm add:*)",
32 + "Bash(pnpm lint:check:*)",
33 + "Bash(pnpm format:check:*)",
34 + "Bash(pnpm list:*)",
35 + "Bash(npx husky init:*)",
36 + "Bash(npx lint-staged:*)",
37 + "Bash(__NEW_LINE_9f2146480c6bc5cf__ echo \"✅ Husky + lint-staged 配置完成!\" echo \"\" echo \"📁 配置文件:\" echo \" - .husky/pre-commit\" echo \" - package.json \\(lint-staged 配置\\)\" echo \"\" echo \"🔧 已配置的 Git Hooks:\" ls -la .husky/)",
38 + "Bash(__NEW_LINE_d9f17a4e47d5be4b__ echo \"╔════════════════════════════════════════════════════════════╗\" echo \"║ ✅ Husky + lint-staged 配置完成! ║\" echo \"╚════════════════════════════════════════════════════════════╝\" echo \"\" echo \"📁 配置文件:\" echo \" • .husky/pre-commit - Git pre-commit hook\" echo \" • package.json - lint-staged 配置\" echo \" • docs/HUSKY_LINT_STAGED.md - 使用文档\" echo \"\" echo \"📦 已安装的包:\" pnpm list husky lint-staged --depth 0)",
39 + "Bash(npx playwright install:*)",
14 "Bash(git push:*)", 40 "Bash(git push:*)",
15 - "Bash(find:*)", 41 + "Bash(pnpm test:e2e:*)",
16 - "mcp__web-search-prime__webSearchPrime", 42 + "mcp__zai-mcp-server__ui_to_artifact",
17 - "mcp__web-reader__webReader" 43 + "mcp__zai-mcp-server__extract_text_from_screenshot",
44 + "mcp__zai-mcp-server__analyze_image",
45 + "Bash(git mv:*)",
46 + "Bash(yarn api:generate:*)",
47 + "Bash(./test-mcp.sh:*)",
48 + "Bash(npx:*)",
49 + "Bash(APIFOX_ACCESS_TOKEN=\"APS-jkT1Q61MCKgzgvfCL2euIR2TcgKsnSyc\" npx -y apifox-mcp-server@latest:*)",
50 + "Bash(git checkout:*)"
18 ] 51 ]
19 } 52 }
20 } 53 }
......