diff --git a/.gitignore b/.gitignore index 090a1f0..33ed394 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea .DS_Store +openapi.yaml diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..a1c3482 --- /dev/null +++ b/buf.gen.yaml @@ -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 diff --git a/buf.yaml b/buf.yaml index 1867327..9a992ec 100644 --- a/buf.yaml +++ b/buf.yaml @@ -1,3 +1,4 @@ +# yaml-language-server: $schema=https://www.schemastore.org/buf.json version: v2 modules: - path: apis diff --git a/generate_openapi.py b/generate_openapi.py new file mode 100644 index 0000000..de47a08 --- /dev/null +++ b/generate_openapi.py @@ -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 ") + 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()