Bootstraps the shared frontend build glue for webapp-template-derived projects: bin/fetch-openapi.sh — pull Swagger JSON from a running backend bin/postprocess-openapi.py — fix oatpp 1.3 rough edges before orval bin/inject-hashed-filenames.py — rewrite HTML tags, config-driven src/vite-config.ts — defineAdminConfig / defineGuestConfig templates/orval.config.template.ts — starting point for derived repos Package name @uschuster/webapp-scaffold. Consumed as a devDependency through the internal Forgejo npm registry; binaries exposed for use in package.json scripts. createCoreFetch + i18n deferred to v0.2 / v0.3. Closes fewo-webapp#414 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
47 lines
1.6 KiB
Python
Executable file
47 lines
1.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""Post-process openapi.json before handing it to Orval.
|
|
|
|
oatpp 1.3's Swagger generator produces a valid spec but with rough edges
|
|
that make the generated client less ergonomic:
|
|
|
|
- Missing operationIds on some endpoints → orval falls back to path-based
|
|
names that collide. We synthesise an operationId from method + path.
|
|
- summary/description strings occasionally contain stray control characters.
|
|
- Some endpoints have no tags, which throws off orval's file-splitting.
|
|
|
|
Run between `fetch-openapi.sh` and `orval` (see package.json `codegen`).
|
|
"""
|
|
import json
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
SRC = Path("openapi.json")
|
|
if not SRC.exists():
|
|
sys.exit(f"{SRC} not found — run fetch-openapi.sh first")
|
|
|
|
spec = json.loads(SRC.read_text())
|
|
|
|
|
|
def op_id(method: str, path: str) -> str:
|
|
"""`getApiAnnouncementsEntityIdHistory` from `GET /api/announcements/{entity_id}/history`."""
|
|
parts = [method.lower()]
|
|
for seg in path.strip("/").split("/"):
|
|
if seg.startswith("{") and seg.endswith("}"):
|
|
parts.append(seg[1:-1])
|
|
else:
|
|
parts.append(seg)
|
|
return re.sub(r"[^A-Za-z0-9]+(\w)", lambda m: m.group(1).upper(),
|
|
"_".join(parts))
|
|
|
|
|
|
paths = spec.get("paths", {})
|
|
for path, methods in paths.items():
|
|
for method, op in methods.items():
|
|
if not isinstance(op, dict):
|
|
continue
|
|
op.setdefault("operationId", op_id(method, path))
|
|
op.setdefault("tags", [path.strip("/").split("/")[1] if "/" in path.strip("/") else "default"])
|
|
|
|
SRC.write_text(json.dumps(spec, indent=2))
|
|
print(f" postprocessed {SRC} — {len(paths)} paths")
|