feat: 完善后端 API OpenAPI 文档与统一错误响应 schema
This commit is contained in:
73
server/scripts/export_openapi.py
Normal file
73
server/scripts/export_openapi.py
Normal file
@@ -0,0 +1,73 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from app.main import create_app
|
||||
|
||||
SERVER_DIR = Path(__file__).resolve().parents[1]
|
||||
ROOT_DIR = SERVER_DIR.parent
|
||||
OUTPUT_DIR = ROOT_DIR / "document" / "development" / "backend_api"
|
||||
OPENAPI_PATH = OUTPUT_DIR / "openapi.json"
|
||||
INVENTORY_PATH = OUTPUT_DIR / "interface_inventory.md"
|
||||
|
||||
|
||||
def build_inventory(schema: dict[str, object]) -> str:
|
||||
paths = schema.get("paths", {})
|
||||
tag_groups: dict[str, list[tuple[str, str, str]]] = defaultdict(list)
|
||||
|
||||
for path, operations in sorted(paths.items()):
|
||||
if not isinstance(operations, dict):
|
||||
continue
|
||||
for method, operation in sorted(operations.items()):
|
||||
if not isinstance(operation, dict):
|
||||
continue
|
||||
summary = str(operation.get("summary") or operation.get("operationId") or "-")
|
||||
tags = operation.get("tags") or ["untagged"]
|
||||
primary_tag = str(tags[0])
|
||||
tag_groups[primary_tag].append((method.upper(), str(path), summary))
|
||||
|
||||
generated_at = datetime.now(UTC).strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||
lines = [
|
||||
"# Backend API Interface Inventory",
|
||||
"",
|
||||
f"- Generated at: `{generated_at}`",
|
||||
f"- API title: `{schema['info']['title']}`",
|
||||
f"- API version: `{schema['info']['version']}`",
|
||||
f"- Total paths: `{len(paths)}`",
|
||||
"",
|
||||
"## Tag Overview",
|
||||
"",
|
||||
]
|
||||
|
||||
for tag_name in sorted(tag_groups):
|
||||
lines.append(f"### {tag_name}")
|
||||
lines.append("")
|
||||
lines.append("| Method | Path | Summary |")
|
||||
lines.append("| --- | --- | --- |")
|
||||
for method, path, summary in tag_groups[tag_name]:
|
||||
lines.append(f"| `{method}` | `{path}` | {summary} |")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines).strip() + "\n"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
app = create_app()
|
||||
schema = app.openapi()
|
||||
|
||||
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
OPENAPI_PATH.write_text(
|
||||
json.dumps(schema, ensure_ascii=False, indent=2),
|
||||
encoding="utf-8",
|
||||
)
|
||||
INVENTORY_PATH.write_text(build_inventory(schema), encoding="utf-8")
|
||||
|
||||
print(f"OpenAPI exported to: {OPENAPI_PATH}")
|
||||
print(f"Interface inventory exported to: {INVENTORY_PATH}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user