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()