import click from .core.parser import parse_openapi_spec from .core.generator import generate_docs from .core.models import APISpec, Endpoint, RequestExample, ResponseExample from .utils.search import search_endpoints @click.group() def main(): """LocalAPI Docs - Generate local API documentation from OpenAPI specs.""" pass @main.command() @click.argument('spec_file', type=click.Path(exists=True)) @click.option('--host', '-h', default='127.0.0.1', help='Host to bind to') @click.option('--port', '-p', default=8080, help='Port to serve on') @click.option('--no-browser', is_flag=True, help='Don\'t open browser automatically') def serve(spec_file, host, port, no_browser): """Start an interactive HTML documentation server.""" from .templates.html_template import generate_html_server generate_html_server(spec_file, host, port, not no_browser) @main.command() @click.argument('spec_file', type=click.Path(exists=True)) @click.option('--output', '-o', help='Output file or directory') @click.option('--format', '-f', type=click.Choice(['html', 'markdown', 'json', 'all']), default='html', help='Output format') @click.option('--open', is_flag=True, help='Open the generated file in browser') def generate(spec_file, output, format, open): """Generate static documentation in various formats.""" generate_docs(spec_file, output, format, open) @main.command() @click.argument('spec_file', type=click.Path(exists=True)) @click.option('--json', is_flag=True, help='Output as JSON') def validate(spec_file, json_output): """Validate an OpenAPI specification file.""" result = parse_openapi_spec(spec_file) if result.get('valid'): click.echo("✓ OpenAPI spec is valid") if json_output: import json click.echo(json.dumps(result, indent=2)) else: click.echo("✗ OpenAPI spec is invalid") if json_output: import json click.echo(json.dumps(result, indent=2)) else: for error in result.get('errors', []): click.echo(f" - {error}") @main.command() @click.argument('spec_file', type=click.Path(exists=True)) @click.argument('query', nargs=-1) @click.option('--limit', '-l', default=10, help='Maximum results') @click.option('--json', is_flag=True, help='Output as JSON') def search(spec_file, query, limit, json_output): """Search for endpoints in an OpenAPI specification.""" search_term = ' '.join(query) results = search_endpoints(spec_file, search_term, limit) if json_output: import json click.echo(json.dumps(results, indent=2)) else: if not results: click.echo("No results found.") return for result in results: click.echo(f"\n{result['method']} {result['path']}") click.echo(f" {result.get('summary', result.get('description', 'No description'))}") click.echo(f" Tags: {', '.join(result.get('tags', []))}")