|
|
#!/usr/bin/env python3
|
|
|
# CodeDetect API文档生成器
|
|
|
|
|
|
import os
|
|
|
import sys
|
|
|
import re
|
|
|
import inspect
|
|
|
import json
|
|
|
from pathlib import Path
|
|
|
from typing import Dict, List, Any, Optional
|
|
|
from dataclasses import dataclass, asdict
|
|
|
|
|
|
@dataclass
|
|
|
class APIEndpoint:
|
|
|
"""API端点信息"""
|
|
|
method: str
|
|
|
path: str
|
|
|
description: str
|
|
|
parameters: List[Dict[str, Any]]
|
|
|
responses: Dict[str, Any]
|
|
|
auth_required: bool = False
|
|
|
|
|
|
@dataclass
|
|
|
class WebSocketEvent:
|
|
|
"""WebSocket事件信息"""
|
|
|
event_name: str
|
|
|
direction: str # 'send' or 'receive'
|
|
|
description: str
|
|
|
data_structure: Dict[str, Any]
|
|
|
|
|
|
class APIDocGenerator:
|
|
|
"""API文档生成器"""
|
|
|
|
|
|
def __init__(self, source_dir: str = "src"):
|
|
|
self.source_dir = Path(source_dir)
|
|
|
self.output_dir = Path("docs/api")
|
|
|
self.endpoints: List[APIEndpoint] = []
|
|
|
self.websocket_events: List[WebSocketEvent] = []
|
|
|
|
|
|
def generate_all_docs(self):
|
|
|
"""生成所有API文档"""
|
|
|
print("🚀 开始生成API文档...")
|
|
|
|
|
|
# 创建输出目录
|
|
|
self.output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
# 扫描源代码
|
|
|
self._scan_api_endpoints()
|
|
|
self._scan_websocket_events()
|
|
|
|
|
|
# 生成文档
|
|
|
self._generate_rest_api_docs()
|
|
|
self._generate_websocket_docs()
|
|
|
self._generate_openapi_spec()
|
|
|
|
|
|
print("✅ API文档生成完成")
|
|
|
|
|
|
def _scan_api_endpoints(self):
|
|
|
"""扫描API端点"""
|
|
|
api_file = self.source_dir / "ui" / "api.py"
|
|
|
if not api_file.exists():
|
|
|
print(f"⚠️ API文件不存在: {api_file}")
|
|
|
return
|
|
|
|
|
|
print("📡 扫描REST API端点...")
|
|
|
|
|
|
# 简单的端点检测逻辑
|
|
|
content = api_file.read_text()
|
|
|
|
|
|
# 查找路由定义
|
|
|
route_pattern = r'@(\w+)\.route\([\'"]([^\'"]+)[\'"](?:,\s*methods=\[([^\]]+)\])?\)'
|
|
|
matches = re.findall(route_pattern, content)
|
|
|
|
|
|
for decorator, path, methods in matches:
|
|
|
if methods:
|
|
|
method_list = [m.strip().strip('\'"') for m in methods.split(',')]
|
|
|
else:
|
|
|
method_list = ['GET']
|
|
|
|
|
|
for method in method_list:
|
|
|
endpoint = APIEndpoint(
|
|
|
method=method,
|
|
|
path=path,
|
|
|
description=f"{method} {path}",
|
|
|
parameters=[],
|
|
|
responses={"200": {"description": "Success"}}
|
|
|
)
|
|
|
self.endpoints.append(endpoint)
|
|
|
|
|
|
print(f" 发现 {len(self.endpoints)} 个API端点")
|
|
|
|
|
|
def _scan_websocket_events(self):
|
|
|
"""扫描WebSocket事件"""
|
|
|
socketio_file = self.source_dir / "ui" / "socketio_handlers.py"
|
|
|
if not socketio_file.exists():
|
|
|
print(f"⚠️ WebSocket文件不存在: {socketio_file}")
|
|
|
return
|
|
|
|
|
|
print("🔌 扫描WebSocket事件...")
|
|
|
|
|
|
content = socketio_file.read_text()
|
|
|
|
|
|
# 查找事件处理器
|
|
|
event_pattern = r'@socketio\.on\([\'"]([^\'"]+)[\'"]\)'
|
|
|
matches = re.findall(event_pattern, content)
|
|
|
|
|
|
for event_name in matches:
|
|
|
event = WebSocketEvent(
|
|
|
event_name=event_name,
|
|
|
direction="receive",
|
|
|
description=f"WebSocket事件: {event_name}",
|
|
|
data_structure={}
|
|
|
)
|
|
|
self.websocket_events.append(event)
|
|
|
|
|
|
print(f" 发现 {len(self.websocket_events)} 个WebSocket事件")
|
|
|
|
|
|
def _generate_rest_api_docs(self):
|
|
|
"""生成REST API文档"""
|
|
|
doc_content = """# CodeDetect REST API 参考
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
CodeDetect提供RESTful API用于代码验证和突变生成。
|
|
|
|
|
|
## 认证
|
|
|
|
|
|
大多数API端点需要认证。使用Bearer Token格式:
|
|
|
|
|
|
```
|
|
|
Authorization: Bearer <your-api-key>
|
|
|
```
|
|
|
|
|
|
## 基础URL
|
|
|
|
|
|
```
|
|
|
http://localhost:5000/api/v1
|
|
|
```
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 按路径分组端点
|
|
|
endpoints_by_path = {}
|
|
|
for endpoint in self.endpoints:
|
|
|
if endpoint.path not in endpoints_by_path:
|
|
|
endpoints_by_path[endpoint.path] = []
|
|
|
endpoints_by_path[endpoint.path].append(endpoint)
|
|
|
|
|
|
# 生成端点文档
|
|
|
for path, path_endpoints in endpoints_by_path.items():
|
|
|
doc_content += f"\n## {path}\n\n"
|
|
|
|
|
|
for endpoint in path_endpoints:
|
|
|
doc_content += f"### {endpoint.method} {path}\n\n"
|
|
|
doc_content += f"{endpoint.description}\n\n"
|
|
|
|
|
|
if endpoint.parameters:
|
|
|
doc_content += "#### 请求参数\n\n"
|
|
|
for param in endpoint.parameters:
|
|
|
doc_content += f"- **{param['name']}** ({param['type']}): {param['description']}\n"
|
|
|
doc_content += "\n"
|
|
|
|
|
|
doc_content += "#### 响应\n\n"
|
|
|
for status, response in endpoint.responses.items():
|
|
|
doc_content += f"**{status}**: {response['description']}\n\n"
|
|
|
|
|
|
doc_content += "---\n\n"
|
|
|
|
|
|
# 写入文件
|
|
|
(self.output_dir / "rest-api.md").write_text(doc_content)
|
|
|
|
|
|
def _generate_websocket_docs(self):
|
|
|
"""生成WebSocket文档"""
|
|
|
doc_content = """# CodeDetect WebSocket API 参考
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
CodeDetect使用WebSocket提供实时更新和进度通知。
|
|
|
|
|
|
## 连接
|
|
|
|
|
|
```javascript
|
|
|
const socket = io('http://localhost:5000');
|
|
|
```
|
|
|
|
|
|
## 事件
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 生成事件文档
|
|
|
for event in self.websocket_events:
|
|
|
doc_content += f"### {event.event_name}\n\n"
|
|
|
doc_content += f"**方向**: {event.direction}\n\n"
|
|
|
doc_content += f"{event.description}\n\n"
|
|
|
|
|
|
if event.data_structure:
|
|
|
doc_content += "#### 数据结构\n\n"
|
|
|
doc_content += "```json\n"
|
|
|
doc_content += json.dumps(event.data_structure, indent=2, ensure_ascii=False)
|
|
|
doc_content += "\n```\n\n"
|
|
|
|
|
|
doc_content += "---\n\n"
|
|
|
|
|
|
# 写入文件
|
|
|
(self.output_dir / "websocket-api.md").write_text(doc_content)
|
|
|
|
|
|
def _generate_openapi_spec(self):
|
|
|
"""生成OpenAPI规范"""
|
|
|
spec = {
|
|
|
"openapi": "3.0.0",
|
|
|
"info": {
|
|
|
"title": "CodeDetect API",
|
|
|
"version": "1.0.0",
|
|
|
"description": "CodeDetect代码验证和突变生成API"
|
|
|
},
|
|
|
"servers": [
|
|
|
{
|
|
|
"url": "http://localhost:5000/api/v1",
|
|
|
"description": "开发服务器"
|
|
|
}
|
|
|
],
|
|
|
"paths": {},
|
|
|
"components": {
|
|
|
"securitySchemes": {
|
|
|
"BearerAuth": {
|
|
|
"type": "http",
|
|
|
"scheme": "bearer",
|
|
|
"bearerFormat": "JWT"
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
# 添加路径
|
|
|
for endpoint in self.endpoints:
|
|
|
path = endpoint.path
|
|
|
method = endpoint.method.lower()
|
|
|
|
|
|
if path not in spec["paths"]:
|
|
|
spec["paths"][path] = {}
|
|
|
|
|
|
spec["paths"][path][method] = {
|
|
|
"summary": endpoint.description,
|
|
|
"responses": endpoint.responses
|
|
|
}
|
|
|
|
|
|
if endpoint.auth_required:
|
|
|
spec["paths"][path][method]["security"] = [{"BearerAuth": []}]
|
|
|
|
|
|
# 写入文件
|
|
|
(self.output_dir / "openapi.json").write_text(
|
|
|
json.dumps(spec, indent=2, ensure_ascii=False)
|
|
|
)
|
|
|
|
|
|
def main():
|
|
|
"""主函数"""
|
|
|
generator = APIDocGenerator()
|
|
|
generator.generate_all_docs()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
main() |