hookehuyr

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

添加完整的API生成器技能,包括从OpenAPI文档生成前端API代码的工具链
更新Claude配置以支持pnpm包管理器和MCP服务器
重构权限设置,优化开发工具链集成
# API Diff Skill
对比两个版本的 OpenAPI 文档或生成的 API 文件,检测接口变更。
## 使用场景
1. **更新 API 后自动检查**:运行 `api:generate` 后自动对比新旧接口
2. **手动对比**:对比两个不同的 OpenAPI 文档
3. **CI/CD 集成**:在部署前检查破坏性 API 变更
## 如何调用
### 在生成 API 后自动对比
```bash
pnpm run api:generate
```
生成器会自动调用对比逻辑,检查是否有接口变更。
### 手动对比两个文档
```bash
# 对比两个 OpenAPI markdown 文档
node scripts/apiDiff.js docs/api-specs/user/api1.md docs/api-specs/user/api1-new.md
# 对比整个模块目录
node scripts/apiDiff.js docs/api-specs/user/ docs/api-specs/user-new/
# 对比生成的 API 文件
node scripts/apiDiff.js src/api/user.js src/api/user-new.js
```
## 对比维度
1. **接口增删**:新增或删除的接口
2. **参数变更**
- 新增必填参数(破坏性变更)
- 删除参数(破坏性变更)
- 参数类型变更(破坏性变更)
- 新增可选参数(非破坏性)
3. **返回值变更**
- 返回结构变更
- 字段类型变更
4. **HTTP 方法变更**:GET ↔ POST(破坏性变更)
## 输出格式
对比结果会以以下格式输出:
```
=== API 变更检测报告 ===
📦 模块: user
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 新增接口 (1):
+ getUserProfile
⚠️ 修改接口 (2):
↪ editUserInfo
✗ [破坏性] 删除必填参数: sms_code
✓ [非破坏性] 新增可选参数: avatar
↪ getUserInfo
✓ [非破坏性] 新增可选参数: include_profile
❌ 删除接口 (1):
- deleteUserAccount
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
总计: 1 新增, 2 修改, 1 删除
⚠️ 检测到 1 个破坏性变更,请仔细检查业务逻辑!
```
## 退出码
- `0`: 无变更或仅有非破坏性变更
- `1`: 检测到破坏性变更(可用于 CI/CD 失败)
## 配置选项
可以通过环境变量配置:
```bash
# 严格模式:任何变更都返回失败码
API_DIFF_STRICT=true node scripts/apiDiff.js ...
# 输出 JSON 格式(用于程序解析)
API_DIFF_FORMAT=json node scripts/apiDiff.js ...
```
## 注意事项
1. 对比逻辑基于 OpenAPI 规范,确保文档格式正确
2. 破坏性变更需要在业务代码中做兼容处理
3. 新增接口通常不需要修改现有代码
4. 删除接口前请确认没有地方在使用
This diff is collapsed. Click to expand it.
#!/bin/bash
# API Generator Skill 安装脚本
# 用于将 API Generator 功能安装到当前项目
set -e
echo "🚀 API Generator Skill 安装程序"
echo "================================"
echo ""
# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# 检查是否在项目根目录
if [ ! -f "package.json" ]; then
echo -e "${RED}❌ 错误: 请在项目根目录运行此脚本${NC}"
exit 1
fi
# 检查 package.json 中是否已有 api:generate 命令
if grep -q '"api:generate"' package.json; then
echo -e "${YELLOW}⚠️ 检测到已存在 api:generate 命令${NC}"
read -p "是否覆盖? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "安装已取消"
exit 0
fi
fi
# 创建目录结构
echo -e "${GREEN}📁 创建目录结构...${NC}"
mkdir -p .claude/custom_skills/api-generator/{scripts,templates,setup}
mkdir -p docs/openAPI
mkdir -p .tmp
# 检查必要的文件
echo -e "${GREEN}📋 检查文件...${NC}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# 检查脚本文件
if [ ! -f "$SCRIPT_DIR/../scripts/generateApiFromOpenAPI.js" ]; then
echo -e "${RED}❌ 缺少 generateApiFromOpenAPI.js${NC}"
exit 1
fi
if [ ! -f "$SCRIPT_DIR/../scripts/apiDiff.js" ]; then
echo -e "${RED}❌ 缺少 apiDiff.js${NC}"
exit 1
fi
# 检查模板文件
if [ ! -f "$SCRIPT_DIR/../templates/openAPI-template.md" ]; then
echo -e "${RED}❌ 缺少 openAPI-template.md${NC}"
exit 1
fi
# 安装依赖
echo -e "${GREEN}📦 检查依赖...${NC}"
if ! command -v pnpm &> /dev/null; then
echo -e "${YELLOW}⚠️ pnpm 未安装,尝试使用 npm...${NC}"
PKG_MANAGER="npm"
else
PKG_MANAGER="pnpm"
fi
# 检查 js-yaml 是否已安装
if ! $PKG_MANAGER list js-yaml &> /dev/null; then
echo -e "${GREEN}📦 安装 js-yaml...${NC}"
$PKG_MANAGER add -D js-yaml
else
echo -e "${GREEN}✅ js-yaml 已安装${NC}"
fi
# 添加 npm scripts
echo -e "${GREEN}🔧 配置 npm scripts...${NC}"
# 使用 jq 或临时文件添加 scripts
if command -v jq &> /dev/null; then
jq '.scripts."api:generate" = "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js" |
.scripts."api:diff" = "node .claude/custom_skills/api-generator/scripts/apiDiff.js"' package.json > package.json.tmp
mv package.json.tmp package.json
else
# 使用 sed 添加(更兼容)
if ! grep -q '"api:generate"' package.json; then
# 找到 "scripts" 行并在后面插入
sed -i '' '/"scripts":/a\
\ "api:generate": "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js",\
\ "api:diff": "node .claude/custom_skills/api-generator/scripts/apiDiff.js",
' package.json 2>/dev/null || sed -i '/"scripts":/a\
\ "api:generate": "node .claude/custom_skills/api-generator/scripts/generateApiFromOpenAPI.js",\
\ "api:diff": "node .claude/custom_skills/api-generator/scripts/apiDiff.js",
' package.json
fi
fi
# 创建示例文档
echo -e "${GREEN}📝 创建示例文档...${NC}"
mkdir -p docs/openAPI/example
cat > docs/openAPI/example/getExample.md << 'EOF'
# 获取示例数据
## OpenAPI Specification
```yaml
openapi: 3.0.1
info:
title: ''
version: 1.0.0
paths:
/srv/:
get:
summary: 获取示例数据
description: 这是一个示例接口,展示如何编写 OpenAPI 文档
tags:
- 示例模块
parameters:
- name: a
in: query
description: action 参数
required: false
example: example_data
schema:
type: string
- name: id
in: query
description: 数据ID
required: true
example: 123
schema:
type: integer
responses:
'200':
description: 成功返回
content:
application/json:
schema:
type: object
properties:
code:
type: integer
description: 0=失败,1=成功
msg:
type: string
description: 错误信息
data:
type: object
properties:
id:
type: integer
description: 数据ID
name:
type: string
description: 名称
created_at:
type: string
description: 创建时间
```
EOF
# 创建 README
cat > docs/openAPI/README.md << 'EOF'
# OpenAPI 文档目录
本目录用于存放 OpenAPI 规范的接口文档,这些文档将自动转换为前端 API 调用代码。
## 目录结构
```
docs/openAPI/
├── example/ # 示例模块
│ └── getExample.md # 示例接口
├── user/ # 用户模块(你的模块)
├── course/ # 课程模块(你的模块)
└── order/ # 订单模块(你的模块)
```
## 如何添加新接口
1. **创建模块目录**(如果不存在)
```bash
mkdir -p docs/openAPI/yourModule
```
2. **创建接口文档**
```bash
# 使用模板创建
cp .claude/custom_skills/api-generator/templates/openAPI-template.md \
docs/openAPI/yourModule/yourApiName.md
```
3. **编辑文档**
- 按照模板填写接口信息
- 遵循 OpenAPI 3.0.1 规范
- 添加详细的参数说明和返回值结构
4. **生成代码**
```bash
pnpm api:generate
```
5. **使用生成的 API**
```javascript
import { yourApiNameAPI } from '@/api/yourModule'
```
## 命令速查
```bash
# 生成 API 代码
pnpm api:generate
# 对比 API 变更
pnpm api:diff docs/openAPI/user/ docs/openAPI/user-new/
# 查看帮助
cat .claude/custom_skills/api-generator/skill.md
```
## 注意事项
- 第一级目录名 = 模块名(会生成 `模块名.js`)
- 第二级文件名 = 接口名(会生成 `接口名API` 函数)
- 所有 `.md` 文件必须包含 YAML 代码块
- 遵循 OpenAPI 3.0.1 规范编写 YAML
## 参考文档
详细使用说明请参考:[API Generator Skill 文档](../../.claude/custom_skills/api-generator/skill.md)
EOF
# 完成
echo ""
echo -e "${GREEN}✅ 安装完成!${NC}"
echo ""
echo "📚 下一步:"
echo " 1. 查看示例文档: cat docs/openAPI/example/getExample.md"
echo " 2. 创建你的第一个接口: cp docs/openAPI/example/getExample.md docs/openAPI/yourModule/yourApi.md"
echo " 3. 生成 API 代码: pnpm api:generate"
echo ""
echo "📖 完整文档: cat .claude/custom_skills/api-generator/skill.md"
echo ""
This diff is collapsed. Click to expand it.
# 接口名称
## 接口描述
详细描述这个接口的功能、使用场景和注意事项。
## OpenAPI Specification
```yaml
openapi: 3.0.1
info:
title: ''
version: 1.0.0
paths:
/srv/:
get: # 或 post
summary: 接口简介(一行描述)
description: |
接口详细说明...
- 使用场景 1
- 使用场景 2
tags:
- 模块名称
parameters: # GET 请求使用 parameters
- name: a
in: query
description: action 参数
required: false
example: your_action_name
schema:
type: string
- name: f
in: query
description: 业务模块
required: false
example: behalo
schema:
type: string
- name: id
in: query
description: 参数描述
required: true # true=必填,false=可选
example: 123
schema:
type: integer
requestBody: # POST 请求使用 requestBody
content:
application/x-www-form-urlencoded: # 或 application/json
schema:
type: object
required:
- course_id
- quantity
properties:
course_id:
type: integer
description: 课程ID
example: 1
quantity:
type: integer
description: 数量
example: 1
responses:
'200':
description: 成功返回
content:
application/json:
schema:
type: object
properties:
code:
type: integer
description: 0=失败,1=成功
msg:
type: string
description: 错误信息
data:
type: object
description: 返回数据
properties:
id:
type: integer
description: 数据ID
name:
type: string
description: 名称
items:
type: array
description: 列表数据
items:
type: object
properties:
item_id:
type: integer
description: 项目ID
item_name:
type: string
description: 项目名称
```
## 使用示例
### GET 请求示例
```javascript
import { getYourAPINameAPI } from '@/api/yourModule'
const { code, data } = await getYourAPINameAPI({
id: 123,
page: 1,
limit: 10
})
if (code === 1) {
console.log('成功:', data)
}
```
### POST 请求示例
```javascript
import { createYourResourceAPI } from '@/api/yourModule'
const { code, data } = await createYourResourceAPI({
course_id: 1,
quantity: 2
})
if (code === 1) {
console.log('创建成功:', data)
}
```
## 注意事项
- **权限要求**: 说明是否需要登录、特殊权限等
- **限流规则**: 说明接口调用频率限制
- **错误码**: 列出常见的错误码及含义
- **兼容性**: 说明版本兼容性要求
## 相关接口
- [相关接口1](./relatedApi1.md)
- [相关接口2](./relatedApi2.md)
## 更新记录
- **2026-01-29**: 初始版本,创建接口
{
"packageManager": "pnpm"
}
{
"mcpServers": {
"mlaj_API_文档": {
"command": "npx",
"args": [
"-y",
"apifox-mcp-server@latest",
"--project-id=6084040"
],
"env": {
"APIFOX_ACCESS_TOKEN": "APS-jkT1Q61MCKgzgvfCL2euIR2TcgKsnSyc"
}
}
}
}
{
"permissions": {
"allow": [
"Bash(pandoc:*)",
"Bash(npx skills --help:*)",
"Bash(pnpm add:*)",
"Bash(pnpm api:generate:*)",
"Bash(node:*)",
"Bash(ls:*)",
"Bash(tree:*)",
"Bash(git checkout:*)",
"Bash(xargs awk:*)",
"Bash(find:*)",
"Bash(grep:*)",
"Bash(git diff:*)",
"mcp__web-search-prime__webSearchPrime",
"mcp__web-reader__webReader",
"Bash(ls:*)",
"Bash(for:*)",
"Bash(do if [ -f \"$dirskill.md\" ])",
"Bash(fi:*)",
"Bash(done:*)",
"Bash(if:*)",
"Bash(then echo \"找到项目本地技能:\")",
"Bash(else echo \"当前项目没有本地技能目录\")",
"Bash(command:*)",
"Bash(then mv \"$dirskill.md\" \"$dirSKILL.md\")",
"Bash(do if [ -f \"$dirSKILL.md\" ])",
"Bash(then rmdir ~/.config/claude-code/skills)",
"Bash(else echo \"目录不为空或不存在,跳过删除\")",
"Bash(chmod:*)",
"Bash(scripts/upload-to-qiniu.sh:*)",
"Bash(curl:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push)",
"Bash(git restore:*)",
"Bash(pnpm add:*)",
"Bash(pnpm lint:check:*)",
"Bash(pnpm format:check:*)",
"Bash(pnpm list:*)",
"Bash(npx husky init:*)",
"Bash(npx lint-staged:*)",
"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/)",
"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)",
"Bash(npx playwright install:*)",
"Bash(git push:*)",
"Bash(find:*)",
"mcp__web-search-prime__webSearchPrime",
"mcp__web-reader__webReader"
"Bash(pnpm test:e2e:*)",
"mcp__zai-mcp-server__ui_to_artifact",
"mcp__zai-mcp-server__extract_text_from_screenshot",
"mcp__zai-mcp-server__analyze_image",
"Bash(git mv:*)",
"Bash(yarn api:generate:*)",
"Bash(./test-mcp.sh:*)",
"Bash(npx:*)",
"Bash(APIFOX_ACCESS_TOKEN=\"APS-jkT1Q61MCKgzgvfCL2euIR2TcgKsnSyc\" npx -y apifox-mcp-server@latest:*)",
"Bash(git checkout:*)"
]
}
}
......