AI-first API testing desktop client built with Python + PyQt6. Features: - Multi-tab HTTP request editor with params/headers/body/auth/tests - KeyValueTable with per-row enable/disable checkboxes and 36px rows - Format JSON button, syntax highlighting, pre-request & test scripts - Collections, environments, history, import/export (Postman v2.1, cURL) - OpenAPI 3.x / Swagger 2.0 local parser (no AI tokens) - EKIKA Odoo API Framework generator — JSON-API, REST JSON, GraphQL, Custom REST JSON with all auth types (instant, no AI tokens) - Persistent AI chat sidebar (Claude-powered co-pilot) with streaming, context-aware suggestions, and one-click Apply to request editor - AI collection generator from any docs URL or pasted spec - WebSocket client, Mock server, Collection runner, Code generator - Dark/light theme engine (global QSS, object-name selectors) - SSL error detection with actionable hints - MIT License Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
"""Export collections to Postman Collection v2.1 JSON."""
|
|
import json
|
|
from app.models import HttpRequest
|
|
from app.core import storage
|
|
|
|
|
|
def export_collection(collection_id: int) -> str:
|
|
collections = storage.get_collections()
|
|
col = next((c for c in collections if c["id"] == collection_id), None)
|
|
if not col:
|
|
raise ValueError(f"Collection {collection_id} not found")
|
|
|
|
items = []
|
|
|
|
def make_request_item(r: dict) -> dict:
|
|
header = [{"key": k, "value": v} for k, v in r.get("headers", {}).items()]
|
|
url_raw = r.get("url", "")
|
|
params = r.get("params", {})
|
|
query = [{"key": k, "value": v} for k, v in params.items()]
|
|
|
|
body_obj = None
|
|
body = r.get("body", "")
|
|
body_type = r.get("body_type", "raw")
|
|
if body:
|
|
if body_type == "urlencoded":
|
|
pairs = []
|
|
for line in body.split("&"):
|
|
if "=" in line:
|
|
k, _, v = line.partition("=")
|
|
pairs.append({"key": k, "value": v})
|
|
body_obj = {"mode": "urlencoded", "urlencoded": pairs}
|
|
else:
|
|
body_obj = {"mode": "raw", "raw": body}
|
|
|
|
item = {
|
|
"name": r.get("name") or url_raw,
|
|
"request": {
|
|
"method": r.get("method", "GET"),
|
|
"header": header,
|
|
"url": {"raw": url_raw, "query": query},
|
|
}
|
|
}
|
|
if body_obj:
|
|
item["request"]["body"] = body_obj
|
|
return item
|
|
|
|
# Top-level requests (no folder)
|
|
for r in storage.get_requests(collection_id):
|
|
items.append(make_request_item(r))
|
|
|
|
# Folders
|
|
for folder in storage.get_folders(collection_id):
|
|
folder_item = {
|
|
"name": folder["name"],
|
|
"item": [make_request_item(r) for r in storage.get_requests(collection_id, folder["id"])]
|
|
}
|
|
items.append(folder_item)
|
|
|
|
collection = {
|
|
"info": {
|
|
"name": col["name"],
|
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
},
|
|
"item": items
|
|
}
|
|
return json.dumps(collection, indent=2)
|