clqms-be/public/bundle-api-docs.py
mahdahar fcaf9b74ea feat: Restructure OpenAPI documentation with modular components
- Add OpenApiDocs controller for serving bundled API docs

- Split monolithic api-docs.yaml into modular components/

- Add organized paths/ directory with endpoint definitions

- Create bundling scripts (JS, PHP, Python) for merging docs

- Add API_DOCS_README.md with documentation guidelines

- Update Routes.php for new API documentation endpoints

- Update swagger.php view and TestDefSiteModel
2026-02-16 14:20:52 +07:00

98 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""
OpenAPI Documentation Bundler
This script merges the modular OpenAPI specification files into a single
api-docs.bundled.yaml file that can be served to Swagger UI or other OpenAPI tools.
It merges paths from the paths/ directory and then uses Redocly CLI to resolve
all $ref references into inline definitions.
Usage: python bundle-api-docs.py
"""
import yaml
import os
import glob
import subprocess
public_dir = os.path.dirname(os.path.abspath(__file__))
components_dir = os.path.join(public_dir, "components", "schemas")
paths_dir = os.path.join(public_dir, "paths")
temp_file = os.path.join(public_dir, "api-docs.merged.yaml")
output_file = os.path.join(public_dir, "api-docs.bundled.yaml")
# Read the base api-docs.yaml
with open(os.path.join(public_dir, "api-docs.yaml"), "r", encoding="utf-8") as f:
api_docs = yaml.safe_load(f)
# Merge paths from all path files
paths = {}
path_files = glob.glob(os.path.join(paths_dir, "*.yaml"))
print(f"Found {len(path_files)} path files to merge...")
for filepath in path_files:
filename = os.path.basename(filepath)
try:
with open(filepath, "r", encoding="utf-8") as f:
parsed = yaml.safe_load(f)
if parsed:
paths.update(parsed)
print(f" [OK] Merged {len(parsed)} paths from {filename}")
except Exception as e:
print(f" [WARN] Failed to parse {filename}: {e}")
# Replace the empty paths with merged paths
api_docs["paths"] = paths
# Write the merged file (still has $refs)
with open(temp_file, "w", encoding="utf-8") as f:
yaml.dump(
api_docs,
f,
default_flow_style=False,
allow_unicode=True,
sort_keys=False,
width=4096,
)
print(f"\n[SUCCESS] Merged paths into: {temp_file}")
print(f" Total paths: {len(paths)}")
# Now use Redocly CLI to resolve all $ref references
print("\nResolving $ref references with Redocly CLI...")
try:
result = subprocess.run(
["redocly", "bundle", temp_file, "-o", output_file],
capture_output=True,
text=True,
cwd=public_dir,
)
if result.returncode == 0:
print(f" [SUCCESS] Resolved all $ref references to: {output_file}")
# Clean up temp file
os.remove(temp_file)
print(f" [CLEANUP] Removed temp file: {temp_file}")
else:
print(f" [ERROR] Redocly CLI failed:")
print(f" {result.stderr}")
exit(1)
except FileNotFoundError:
print(" [ERROR] Redocly CLI not found. Install with: npm install -g @redocly/cli")
exit(1)
except Exception as e:
print(f" [ERROR] Failed to run Redocly CLI: {e}")
exit(1)
print(f"\n{'=' * 60}")
print(f"Bundling complete!")
print(f" Output: {output_file}")
print(f" Total paths: {len(paths)}")
print(f" Total schemas: {len(api_docs.get('components', {}).get('schemas', {}))}")
print(f"\nYou can now serve this file to Swagger UI.")
print(f"{'=' * 60}")