"""OpenAPI parser — extracts ApiContract entities from OpenAPI YAML specifications.""" from __future__ import annotations from pathlib import Path from typing import Any import yaml from app.modules.design.domain.entities import ApiContract class OpenapiParser: """Parse OpenAPI YAML file and return dict mapping entity type name to list of instances. Returns {'api_contracts': [ApiContract, ...]} """ def parse(self, file_path: Path) -> dict[str, list[Any]]: try: with open(file_path, encoding="utf-8") as f: spec = yaml.safe_load(f) except Exception: return {} if not isinstance(spec, dict) or "paths" not in spec: return {} contracts: list[ApiContract] = [] paths = spec["paths"] if not isinstance(paths, dict): return {} for path, path_item in paths.items(): if not isinstance(path_item, dict): continue for method, operation in path_item.items(): # Skip non-HTTP-method keys (e.g., 'parameters', 'summary') if method.lower() not in ( "get", "post", "put", "delete", "patch", "options", "head", "trace", ): continue if not isinstance(operation, dict): continue operation_id = operation.get("operationId", "") summary = operation.get("summary", "") doc_id = f"API-{operation_id or method.upper()}-{path}" contracts.append(ApiContract( doc_id=doc_id, path=path, method=method.upper(), operation_id=operation_id or "", summary=summary or "", )) if not contracts: return {} return {"api_contracts": contracts}