Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea
.DS_Store
openapi.yaml
7 changes: 7 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# yaml-language-server: $schema=https://www.schemastore.org/buf.gen.json
version: v2
plugins:
# protoc-gen-connect-openapi must be installed locally
# See https://github.com/sudorandom/protoc-gen-connect-openapi
- local: protoc-gen-connect-openapi
out: openapi
1 change: 1 addition & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=https://www.schemastore.org/buf.json
version: v2
modules:
- path: apis
Expand Down
89 changes: 89 additions & 0 deletions generate_openapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# /// script
# dependencies = [
# "ruamel-yaml",
# ]
# ///

import os
import sys
from ruamel.yaml import YAML
from pathlib import Path
from typing import Dict, Any
import tempfile

override = {
"info": {
"title": "Tilebox API",
"version": "1.0.0",
},
"servers": [
{
"url": "https://api.tilebox.com",
},
],
"components": {
"schemas": {
"connect-protocol-version": {
"default": 1,
},
},
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
},
},
},
"security": [
{
"bearerAuth": [],
},
],
}


def recursive_merge(base: Dict[Any, Any], update: Dict[Any, Any]):
for key, value in update.items():
if key in base and isinstance(base[key], dict) and isinstance(value, dict):
# Both values are dictionaries, merge recursively
recursive_merge(base[key], value)
else:
# Either key doesn't exist in base, or one of the values is not a dict
base[key] = value


def main() -> None:
output = "openapi.yaml"
if len(sys.argv) == 2:
output = sys.argv[1]
elif len(sys.argv) != 1:
print("Usage: uv run generate-openapi.py <output>")
sys.exit(1)

tmpdir = tempfile.TemporaryDirectory()
print(f"Generating protobuf to {tmpdir.name}")
os.system(f"buf generate -o {tmpdir.name}")

yaml = YAML(typ="safe")
yaml.default_flow_style = False

merged_yaml = {}

for path in Path(tmpdir.name).glob("**/*.yaml"):
print(f"Merging {path}")

with open(path) as f:
data = yaml.load(f.read())
recursive_merge(merged_yaml, data)

recursive_merge(merged_yaml, override)

tmpdir.cleanup()

print(f"Writing merged output to {output}")
with open(output, "w") as out:
yaml.dump(merged_yaml, out)


if __name__ == "__main__":
main()