"""Crea una request REST dentro de una team collection de Hoppscotch. Construye el HoppRESTRequest canonico (reusando build_hoppscotch_collection del registry) y lo inserta en una team collection via la mutation GraphQL createRequestInCollection del backend self-hosted. La mutation esta protegida por GqlAuthGuard: el JWT de sesion viaja en la cookie `access_token`. """ import json import requests from infra.build_hoppscotch_collection import build_hoppscotch_collection _MUTATION = ( "mutation($c:ID!,$d:CreateTeamRequestInput!){" " createRequestInCollection(collectionID:$c, data:$d){ id title } }" ) def hoppscotch_create_request( collection_id: str, method: str, url: str, *, title: str | None = None, headers: dict | None = None, body: str | None = None, body_type: str | None = None, team_id: str | None = None, access_token: str, backend_url: str = "http://localhost:3170", ) -> dict: """Crea una request en una team collection de Hoppscotch. Args: collection_id: ID de la team collection donde insertar la request. method: metodo HTTP de la request (GET, POST, ...). url: endpoint de la request. title: nombre visible de la request en la GUI. None = derivar de method + path via build_hoppscotch_collection. headers: dict name->value de cabeceras de la request. body: cuerpo de la request como texto ya serializado. body_type: tipo de cuerpo ("json"|"form"|"raw"|None). team_id: ID de la team duena de la collection. Requerido por las versiones del backend cuyo CreateTeamRequestInput exige `teamID` (el self-host de referencia lo exige). Si el backend no lo pide, dejar None. access_token: JWT de sesion (de hoppscotch_login). Viaja en la cookie `access_token`, NO en el header Authorization. backend_url: base del backend Hoppscotch (sin barra final). Returns: Dict. En exito: ``{"status": "ok", "id": str, "title": str}``. En error (GraphQL errors, HTTP no 200, transporte): ``{"status": "error", "error": str, "data": ...}`` con el cuerpo GraphQL si lo hubo. """ spec = { "method": method, "url": url, "headers": headers or {}, "body": body, "body_type": body_type, } req_names = [title] if title else None req_item = build_hoppscotch_collection([spec], request_names=req_names)[ "requests" ][0] data: dict = { "title": req_item["name"], "request": json.dumps(req_item), } if team_id is not None: data["teamID"] = team_id payload = { "query": _MUTATION, "variables": { "c": collection_id, "d": data, }, } try: resp = requests.post( f"{backend_url}/graphql", json=payload, cookies={"access_token": access_token}, timeout=30.0, ) except requests.RequestException as exc: return {"status": "error", "error": f"transport error: {exc}"} try: data = resp.json() except ValueError: return { "status": "error", "error": f"non-JSON response (HTTP {resp.status_code})", } if data.get("errors"): return { "status": "error", "error": "graphql errors", "data": data, } created = (data.get("data") or {}).get("createRequestInCollection") if not created or not created.get("id"): return { "status": "error", "error": "createRequestInCollection returned no id", "data": data, } return { "status": "ok", "id": created["id"], "title": created.get("title"), }