feat: codegen routes — sanitize resource names, --inject-request/--package, expand form bodies
codegen_routes.generate_routes now sanitizes resource identifiers (fetch-requests -> fetch_requests), optionally prepends 'request: Request' (inject_request) and emits <resource>/routes.py packages with __init__.py (package). multipart/form-data and x-www-form-urlencoded bodies expand to per-property UploadFile/File/Form params instead of an opaque dict; spec paths are normalized to forward slashes to avoid Windows escape issues. Adds CLI flags --inject-request/--package, 7 focused tests, and refreshes lib/wiki/MCP docs to the real CLI.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"module": "openapi_first.templates.health_app",
|
||||
"content": {
|
||||
"path": "openapi_first.templates.health_app",
|
||||
"docstring": "OpenAPI-first FastAPI application template.\n\nThis package contains a minimal, fully working example of an\nOpenAPI-first FastAPI service built using the ``openapi_first`` library.\n\nThe application is assembled exclusively from:\n- an OpenAPI specification (``openapi.yaml``)\n- a handler namespace (``routes``)\n\nNo routing decorators, implicit behavior, or framework-specific\nconvenience abstractions are used. All HTTP routes, methods, and\noperation bindings are defined in OpenAPI and enforced at application\nstartup.\n\nThis package is intended to be copied as a starting point for new\nservices via the ``openapi-first`` CLI. It is not part of the\n``openapi_first`` library API surface.\n\n----------------------------------------------------------------------\nScaffolding via CLI\n----------------------------------------------------------------------\n\nCreate a new OpenAPI-first health check service using the bundled\ntemplate:\n\n openapi-first health_app\n\nCreate the service in a custom directory:\n\n openapi-first health_app my-health-service\n\nList all available application templates:\n\n openapi-first --list\n\nThe CLI copies template files verbatim into the target directory.\nNo code is generated or modified beyond the copied scaffold.\n\n----------------------------------------------------------------------\nClient Usage Example\n----------------------------------------------------------------------\n\nThe same OpenAPI specification used by the server can be used to\nconstruct a strict, operationId-driven HTTP client.\n\nExample client call for the ``get_health`` operation:\n\n from openapi_first.loader import load_openapi\n from openapi_first.client import OpenAPIClient\n\n spec = load_openapi(\"openapi.yaml\")\n client = OpenAPIClient(spec)\n\n response = client.get_health()\n\n assert response.status_code == 200\n assert response.json() == {\"status\": \"ok\"}\n\nClient guarantees:\n- One callable per OpenAPI ``operationId``\n- No hardcoded URLs or HTTP methods in user code\n- Path and request parameters must match the OpenAPI specification\n- Invalid or incomplete OpenAPI specs fail at client construction time",
|
||||
"docstring": "OpenAPI-first FastAPI application template.\n\nThis package contains a minimal, fully working example of an\nOpenAPI-first FastAPI service built using the ``openapi_first`` library.\n\nThe application is assembled exclusively from:\n- an OpenAPI specification (``openapi.yaml``)\n- a handler namespace (``routes``)\n\nNo routing decorators, implicit behavior, or framework-specific\nconvenience abstractions are used. All HTTP routes, methods, and\noperation bindings are defined in OpenAPI and enforced at application\nstartup.\n\nThis package is intended to be copied as a starting point for new\nservices via the ``openapi-first`` CLI. It is not part of the\n``openapi_first`` library API surface.\n\n----------------------------------------------------------------------\nScaffolding via CLI\n----------------------------------------------------------------------\n\nCreate a new OpenAPI-first health check service using the bundled\ntemplate:\n\n openapi-first scaffold health_app\n\nCreate the service in a custom directory:\n\n openapi-first scaffold health_app my-health-service\n\nList all available application templates:\n\n openapi-first scaffold --list\n\nThe CLI copies template files verbatim into the target directory.\nNo code is generated or modified beyond the copied scaffold.\n\n----------------------------------------------------------------------\nClient Usage Example\n----------------------------------------------------------------------\n\nThe same OpenAPI specification used by the server can be used to\nconstruct a strict, operationId-driven HTTP client.\n\nExample client call for the ``get_health`` operation:\n\n from openapi_first.loader import load_openapi\n from openapi_first.client import OpenAPIClient\n\n spec = load_openapi(\"openapi.yaml\")\n client = OpenAPIClient(spec)\n\n response = client.get_health()\n\n assert response.status_code == 200\n assert response.json() == {\"status\": \"ok\"}\n\nClient guarantees:\n- One callable per OpenAPI ``operationId``\n- No hardcoded URLs or HTTP methods in user code\n- Path and request parameters must match the OpenAPI specification\n- Invalid or incomplete OpenAPI specs fail at client construction time",
|
||||
"objects": {
|
||||
"main": {
|
||||
"name": "main",
|
||||
@@ -15,25 +15,18 @@
|
||||
"name": "OpenAPIFirstApp",
|
||||
"kind": "class",
|
||||
"path": "openapi_first.templates.health_app.main.OpenAPIFirstApp",
|
||||
"signature": "<bound method Alias.signature of Alias('OpenAPIFirstApp', 'openapi_first.app.OpenAPIFirstApp')>",
|
||||
"docstring": "FastAPI application enforcing OpenAPI-first design.\n\nNotes:\n **Responsibilities:**\n\n - `OpenAPIFirstApp` subclasses `FastAPI` and replaces manual route\n registration with OpenAPI-driven binding.\n - All routes are derived from the provided OpenAPI specification,\n and each ``operationId`` is mapped to a Python function in the\n supplied routes module.\n - Auth dependencies are auto-injected from the spec's\n ``securitySchemes`` and per-operation ``security`` fields.\n\n **Guarantees:**\n\n - No route can exist without an OpenAPI declaration.\n - No OpenAPI operation can exist without a handler.\n - Swagger UI and ``/openapi.json`` always reflect the provided spec.\n - Handler functions remain framework-agnostic and testable.\n - Auth enforcement is driven entirely by the spec — no manual\n middleware or decorators required.\n\nExample:\n ```python\n from openapi_first import OpenAPIFirstApp\n import app.routes as routes\n\n app = OpenAPIFirstApp(\n openapi_path=\"app/openapi.json\",\n routes_module=routes,\n title=\"Example Service\",\n )\n ```",
|
||||
"signature": "OpenAPIFirstApp(*, openapi_path: str, routes_module: Any, **fastapi_kwargs: Any)",
|
||||
"docstring": "FastAPI application enforcing OpenAPI-first design.\n\nArgs:\n openapi_path (str):\n Filesystem path to the OpenAPI 3.x specification file. This\n specification is treated as the authoritative API contract.\n routes_module (ModuleType):\n Python module containing handler functions whose names correspond\n exactly to OpenAPI ``operationId`` values.\n **fastapi_kwargs (Any):\n Additional keyword arguments passed directly to\n ``fastapi.FastAPI`` (e.g., title, version, middleware, lifespan\n handlers).\n\nRaises:\n OpenAPIFirstError:\n If the OpenAPI specification is invalid, or if any declared\n ``operationId`` does not have a corresponding handler function.\n\nNotes:\n **Responsibilities:**\n\n - `OpenAPIFirstApp` subclasses `FastAPI` and replaces manual route\n registration with OpenAPI-driven binding.\n - All routes are derived from the provided OpenAPI specification,\n and each ``operationId`` is mapped to a Python function in the\n supplied routes module.\n - Auth dependencies are auto-injected from the spec's\n ``securitySchemes`` and per-operation ``security`` fields.\n\n **Guarantees:**\n\n - No route can exist without an OpenAPI declaration.\n - No OpenAPI operation can exist without a handler.\n - Swagger UI and ``/openapi.json`` always reflect the provided spec.\n - Handler functions remain framework-agnostic and testable.\n - Auth enforcement is driven entirely by the spec — no manual\n middleware or decorators required.\n\nExample:\n ```python\n from openapi_first.app import OpenAPIFirstApp\n import app.routes as routes\n\n app = OpenAPIFirstApp(\n openapi_path=\"app/openapi.json\",\n routes_module=routes,\n title=\"Example Service\",\n )\n ```",
|
||||
"members": {
|
||||
"openapi": {
|
||||
"name": "openapi",
|
||||
"kind": "attribute",
|
||||
"path": "openapi_first.templates.health_app.main.OpenAPIFirstApp.openapi",
|
||||
"signature": "<bound method Alias.signature of Alias('openapi', 'openapi_first.app.OpenAPIFirstApp.openapi')>",
|
||||
"signature": null,
|
||||
"docstring": null
|
||||
}
|
||||
}
|
||||
},
|
||||
"routes": {
|
||||
"name": "routes",
|
||||
"kind": "alias",
|
||||
"path": "openapi_first.templates.health_app.main.routes",
|
||||
"signature": "<bound method Alias.signature of Alias('routes', 'routes')>",
|
||||
"docstring": null
|
||||
},
|
||||
"app": {
|
||||
"name": "app",
|
||||
"kind": "attribute",
|
||||
@@ -54,7 +47,7 @@
|
||||
"name": "get_health",
|
||||
"kind": "function",
|
||||
"path": "openapi_first.templates.health_app.routes.get_health",
|
||||
"signature": "<bound method Function.signature of Function('get_health', 16, 32)>",
|
||||
"signature": "get_health() -> dict",
|
||||
"docstring": "Health check operation handler.\n\nThis function implements the OpenAPI operation identified by\n``operationId: get_health``.\n\nIt contains no routing metadata or framework-specific logic.\nRequest binding, HTTP method, and response semantics are defined\nexclusively by the OpenAPI specification.\n\nReturns\n-------\ndict\n A minimal liveness payload indicating service health."
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user