1import json
2import sys
3
4import click
5import requests
6
7from plain.cli import register_cli
8from plain.runtime import settings
9from plain.utils.module_loading import import_string
10
11from .openapi.generator import OpenAPISchemaGenerator
12
13
14@register_cli("api")
15@click.group()
16def cli():
17 """API commands."""
18 pass
19
20
21@cli.command()
22@click.option("--validate", is_flag=True, help="Validate the OpenAPI schema.")
23@click.option("--indent", default=2, help="Indentation level for JSON and YAML output.")
24@click.option(
25 "--format",
26 default="json",
27 help="Output format (json or yaml).",
28 type=click.Choice(["json", "yaml"]),
29)
30def generate_openapi(validate, indent, format):
31 if not settings.API_OPENAPI_ROUTER:
32 click.secho("No OpenAPI URL router configured.", fg="red", err=True)
33 sys.exit(1)
34
35 url_router_class = import_string(settings.API_OPENAPI_ROUTER)
36
37 schema = OpenAPISchemaGenerator(url_router_class)
38
39 if format == "json":
40 print(schema.as_json(indent=indent))
41 elif format == "yaml":
42 print(schema.as_yaml(indent=indent))
43
44 if validate:
45 click.secho("\nOpenAPI schema validation: ", err=True, nl=False)
46 response = requests.post(
47 "https://validator.swagger.io/validator/debug",
48 headers={"Content-Type": "application/json"},
49 json=schema.schema,
50 )
51 response.raise_for_status()
52 failed = response.json().get(
53 "schemaValidationMessages", []
54 ) or response.json().get("messages", [])
55 if failed:
56 click.secho("Failed", fg="red", err=True)
57 click.secho(
58 json.dumps(response.json(), indent=2, sort_keys=True),
59 fg="yellow",
60 err=True,
61 )
62 sys.exit(1)
63 else:
64 click.secho("Success", fg="green", err=True)