hexastack-fastapi 0.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hexastack-fastapi might be problematic. Click here for more details.

Files changed (27) hide show
  1. hexastack_fastapi-0.0.0/PKG-INFO +169 -0
  2. hexastack_fastapi-0.0.0/README.md +148 -0
  3. hexastack_fastapi-0.0.0/pyproject.toml +43 -0
  4. hexastack_fastapi-0.0.0/pyproject.toml.orig +44 -0
  5. hexastack_fastapi-0.0.0/src/hexastack_fastapi/__init__.py +6 -0
  6. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/__init__.py +41 -0
  7. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/app.py +118 -0
  8. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/db_session.py +160 -0
  9. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/dependencies.py +190 -0
  10. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/docs.py +80 -0
  11. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/health.py +62 -0
  12. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/routing.py +203 -0
  13. hexastack_fastapi-0.0.0/src/hexastack_fastapi/adapters/ui.py +491 -0
  14. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/__init__.py +41 -0
  15. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/autodiscovery.py +103 -0
  16. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/bootstrap.py +85 -0
  17. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/config.py +113 -0
  18. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/decorators.py +199 -0
  19. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/exception_handlers.py +60 -0
  20. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/middleware/__init__.py +11 -0
  21. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/middleware/correlation.py +100 -0
  22. hexastack_fastapi-0.0.0/src/hexastack_fastapi/infra/middleware/logging.py +95 -0
  23. hexastack_fastapi-0.0.0/src/hexastack_fastapi/py.typed +0 -0
  24. hexastack_fastapi-0.0.0/src/hexastack_fastapi/testing/__init__.py +18 -0
  25. hexastack_fastapi-0.0.0/src/hexastack_fastapi/testing/cursor.py +115 -0
  26. hexastack_fastapi-0.0.0/src/hexastack_fastapi/testing/recorder.py +238 -0
  27. hexastack_fastapi-0.0.0/src/hexastack_fastapi/testing/server.py +120 -0
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.3
2
+ Name: hexastack-fastapi
3
+ Version: 0.0.0
4
+ Summary: FastAPI presentation adapter for Hexastack
5
+ Author: Richard West
6
+ Author-email: Richard West <dopplereffect.us@gmail.com>
7
+ Requires-Dist: fastapi>=0.141.1
8
+ Requires-Dist: hexastack-core
9
+ Requires-Dist: hexastack-cqrs
10
+ Requires-Dist: hexastack-auth ; extra == 'auth'
11
+ Requires-Dist: zensical>=0.0.56 ; extra == 'docs'
12
+ Requires-Dist: playwright>=1.49.0 ; extra == 'testing'
13
+ Requires-Dist: schemathesis>=3.39.0 ; extra == 'testing'
14
+ Requires-Dist: nicegui>=2.0.0 ; extra == 'ui'
15
+ Requires-Python: >=3.13
16
+ Provides-Extra: auth
17
+ Provides-Extra: docs
18
+ Provides-Extra: testing
19
+ Provides-Extra: ui
20
+ Description-Content-Type: text/markdown
21
+
22
+ # hexastack-fastapi
23
+
24
+ > FastAPI presentation adapter for Hexastack: automatic CQRS routing, database session middleware, exception mapping, and health check endpoints.
25
+
26
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
27
+
28
+ ---
29
+
30
+ ## 1. Overview & Capabilities
31
+
32
+ - **Automatic CQRS Routing & Feature Gating**: Map HTTP endpoints directly to `CommandBusPort` or `QueryBusPort` using `@api_command` and `@api_query`, with native feature flag route guards (`@feature_flag_route` and `require_feature(...)`).
33
+ - **Decoupled Database Session Middleware**: `DbSessionMiddleware` (sync) and `AsyncDbSessionMiddleware` (async) manage session-per-request lifecycles by consuming sessionmakers from DI without a hard dependency on `hexastack-db`.
34
+ - **Standardized Exception Handlers**: Automatically translates domain exceptions (`EntityNotFoundError`, `UniqueConstraintViolationError`, `HexastackError`) into appropriate HTTP status codes (404, 409, 500) and structured JSON error envelopes.
35
+ - **Observability & Correlation Middleware**: Injects `X-Correlation-ID` headers and logs HTTP request lifecycles.
36
+ - **Built-in Health Checks**: Configurable `/health` and `/ready` endpoints verifying container and subsystem readiness.
37
+ - **NiceGUI Reactive UI & DevTools Dashboard**: Optional `[ui]` presentation adapter providing `ui_page`, `dispatch_command`, `dispatch_query`, and a zero-config interactive developer console (`mount_devtools_dashboard`) for inspecting CQRS buses, feature flags, and DI services.
38
+
39
+ ---
40
+
41
+ ## 2. Package Anatomy & Key Components
42
+
43
+ ```
44
+ hexastack_fastapi/
45
+ ├── domain/ # HealthStatus, HTTP error envelope models
46
+ ├── adapters/ # create_app, routing decorators, health endpoints, db_session middleware, dependencies, NiceGUI UI adapter
47
+ └── infra/ # FastApiBootstrapper (order=30), exception handlers, correlation/logging middlewares
48
+ ```
49
+
50
+ ### Key Exports
51
+
52
+ | Category | Exports |
53
+ |---|---|
54
+ | **Application Factory** | `create_app`, `FastApiBootstrapper` (order=30) |
55
+ | **Decorators** | `@api_command`, `@api_query`, `@feature_flag_route`, `RouteMetadata` |
56
+ | **Dependencies** | `get_container`, `get_pipeline`, `get_feature_flags`, `require_feature` |
57
+ | **Documentation Mounting** | `mount_zensical_docs`, `DocumentationNotFoundError`, `ZensicalDocsConfig` |
58
+ | **Exception Handlers** | `register_exception_handlers`, `domain_exception_handler` |
59
+ | **Middlewares** | `DbSessionMiddleware`, `AsyncDbSessionMiddleware`, `add_db_session_middleware`, `CorrelationMiddleware`, `HttpLoggingMiddleware` |
60
+ | **Reactive UI (NiceGUI)** | `dispatch_command`, `dispatch_query`, `mount_devtools_dashboard`, `mount_ui_app`, `ui_page` |
61
+ | **Routing** | `CqrsRouter`, `autodiscover_routes` |
62
+ | **Testing, E2E & Demo Narration** | `create_test_client`, `check_openapi_conformance`, `EphemeralServer`, `ephemeral_server`, `find_free_port`, `smart_click`, `DemoNarrator`, `VIRTUAL_CURSOR_SCRIPT` |
63
+
64
+ ---
65
+
66
+ ## 3. Monorepo & Sibling Relationships
67
+
68
+ ```mermaid
69
+ graph TD
70
+ subgraph ClientRequests ["Client HTTP Inbound"]
71
+ HTTP["HTTP Client Requests"]
72
+ end
73
+
74
+ subgraph FastApiLayer ["hexastack-fastapi"]
75
+ APP["FastAPI Application"]
76
+ MW["Middleware (Correlation, HTTP Logging, DB Session)"]
77
+ ROUTER["CQRS Route Dispatcher"]
78
+ end
79
+
80
+ subgraph CQRSExecution ["hexastack-cqrs"]
81
+ CBUS["CommandBusPort"]
82
+ QBUS["QueryBusPort"]
83
+ end
84
+
85
+ subgraph DecoupledProviders ["Decoupled Providers (via DI)"]
86
+ DB_FACTORY["sessionmaker / async_sessionmaker (from hexastack-db)"]
87
+ LOG_PORT["LoggerPort (from hexastack-logging)"]
88
+ end
89
+
90
+ HTTP --> APP
91
+ APP --> MW
92
+ MW --> ROUTER
93
+ ROUTER -->|dispatches to| CBUS
94
+ ROUTER -->|dispatches to| QBUS
95
+
96
+ MW -. consumes session factory from DI .-> DB_FACTORY
97
+ MW -. consumes LoggerPort from DI .-> LOG_PORT
98
+ ```
99
+
100
+ ### Explicit Dependencies (Direct)
101
+ - `hexastack-core`: DI container, core ports, exception registry, and context propagation.
102
+ - `hexastack-cqrs`: `CommandBusPort` and `QueryBusPort` for message dispatching.
103
+ - `fastapi>=0.141.1`: Web framework and ASGI routing.
104
+
105
+ ### Implied / Behavioral Relationships (DI-Mediated)
106
+ - **Zero-Dependency DB Session Management**: `DbSessionMiddleware` dynamically resolves SQLAlchemy `sessionmaker` from DI without directly importing `hexastack-db`.
107
+ - **Telemetry Integration**: `HttpLoggingMiddleware` outputs structured request telemetry through `LoggerPort`.
108
+ - **Exception Mapping**: Registers global exception handlers translating core domain errors into standard HTTP error responses.
109
+
110
+ ---
111
+
112
+ ## 4. Installation
113
+
114
+ ```bash
115
+ # Standalone install
116
+ pip install hexastack-fastapi
117
+
118
+ # With Uvicorn development server
119
+ pip install "hexastack-fastapi[web]" # or: pip install "hexastack[web]"
120
+
121
+ # Via umbrella package
122
+ pip install "hexastack[fastapi]"
123
+ ```
124
+
125
+ ---
126
+
127
+ ## 5. Configuration Reference
128
+
129
+ ```toml
130
+ [hexastack.fastapi]
131
+ title = "Hexastack API"
132
+ version = "1.0.0"
133
+ docs_url = "/docs"
134
+ openapi_url = "/openapi.json"
135
+ cors_origins = ["*"]
136
+ enable_correlation_header = true
137
+ ```
138
+
139
+ ---
140
+
141
+ ## 6. Quickstart Example
142
+
143
+ ```python
144
+ from dataclasses import dataclass
145
+ from fastapi.testclient import TestClient
146
+ from hexastack_core.infra.bootstrap import bootstrap
147
+ from hexastack_cqrs.domain.query import Query
148
+ from hexastack_cqrs.infra.decorators import query_handler
149
+ from hexastack_fastapi.adapters.app import create_app
150
+
151
+
152
+ @dataclass(frozen=True)
153
+ class GetGreetingQuery(Query):
154
+ name: str
155
+
156
+
157
+ @query_handler(GetGreetingQuery)
158
+ class GetGreetingHandler:
159
+ def __call__(self, qry: GetGreetingQuery) -> dict:
160
+ return {"message": f"Hello, {qry.name}!"}
161
+
162
+
163
+ runtime = bootstrap(packages_to_scan=[__name__])
164
+ app = create_app(runtime)
165
+
166
+ client = TestClient(app)
167
+ response = client.get("/health")
168
+ print(response.json()) # {"status": "healthy"}
169
+ ```
@@ -0,0 +1,148 @@
1
+ # hexastack-fastapi
2
+
3
+ > FastAPI presentation adapter for Hexastack: automatic CQRS routing, database session middleware, exception mapping, and health check endpoints.
4
+
5
+ [![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
6
+
7
+ ---
8
+
9
+ ## 1. Overview & Capabilities
10
+
11
+ - **Automatic CQRS Routing & Feature Gating**: Map HTTP endpoints directly to `CommandBusPort` or `QueryBusPort` using `@api_command` and `@api_query`, with native feature flag route guards (`@feature_flag_route` and `require_feature(...)`).
12
+ - **Decoupled Database Session Middleware**: `DbSessionMiddleware` (sync) and `AsyncDbSessionMiddleware` (async) manage session-per-request lifecycles by consuming sessionmakers from DI without a hard dependency on `hexastack-db`.
13
+ - **Standardized Exception Handlers**: Automatically translates domain exceptions (`EntityNotFoundError`, `UniqueConstraintViolationError`, `HexastackError`) into appropriate HTTP status codes (404, 409, 500) and structured JSON error envelopes.
14
+ - **Observability & Correlation Middleware**: Injects `X-Correlation-ID` headers and logs HTTP request lifecycles.
15
+ - **Built-in Health Checks**: Configurable `/health` and `/ready` endpoints verifying container and subsystem readiness.
16
+ - **NiceGUI Reactive UI & DevTools Dashboard**: Optional `[ui]` presentation adapter providing `ui_page`, `dispatch_command`, `dispatch_query`, and a zero-config interactive developer console (`mount_devtools_dashboard`) for inspecting CQRS buses, feature flags, and DI services.
17
+
18
+ ---
19
+
20
+ ## 2. Package Anatomy & Key Components
21
+
22
+ ```
23
+ hexastack_fastapi/
24
+ ├── domain/ # HealthStatus, HTTP error envelope models
25
+ ├── adapters/ # create_app, routing decorators, health endpoints, db_session middleware, dependencies, NiceGUI UI adapter
26
+ └── infra/ # FastApiBootstrapper (order=30), exception handlers, correlation/logging middlewares
27
+ ```
28
+
29
+ ### Key Exports
30
+
31
+ | Category | Exports |
32
+ |---|---|
33
+ | **Application Factory** | `create_app`, `FastApiBootstrapper` (order=30) |
34
+ | **Decorators** | `@api_command`, `@api_query`, `@feature_flag_route`, `RouteMetadata` |
35
+ | **Dependencies** | `get_container`, `get_pipeline`, `get_feature_flags`, `require_feature` |
36
+ | **Documentation Mounting** | `mount_zensical_docs`, `DocumentationNotFoundError`, `ZensicalDocsConfig` |
37
+ | **Exception Handlers** | `register_exception_handlers`, `domain_exception_handler` |
38
+ | **Middlewares** | `DbSessionMiddleware`, `AsyncDbSessionMiddleware`, `add_db_session_middleware`, `CorrelationMiddleware`, `HttpLoggingMiddleware` |
39
+ | **Reactive UI (NiceGUI)** | `dispatch_command`, `dispatch_query`, `mount_devtools_dashboard`, `mount_ui_app`, `ui_page` |
40
+ | **Routing** | `CqrsRouter`, `autodiscover_routes` |
41
+ | **Testing, E2E & Demo Narration** | `create_test_client`, `check_openapi_conformance`, `EphemeralServer`, `ephemeral_server`, `find_free_port`, `smart_click`, `DemoNarrator`, `VIRTUAL_CURSOR_SCRIPT` |
42
+
43
+ ---
44
+
45
+ ## 3. Monorepo & Sibling Relationships
46
+
47
+ ```mermaid
48
+ graph TD
49
+ subgraph ClientRequests ["Client HTTP Inbound"]
50
+ HTTP["HTTP Client Requests"]
51
+ end
52
+
53
+ subgraph FastApiLayer ["hexastack-fastapi"]
54
+ APP["FastAPI Application"]
55
+ MW["Middleware (Correlation, HTTP Logging, DB Session)"]
56
+ ROUTER["CQRS Route Dispatcher"]
57
+ end
58
+
59
+ subgraph CQRSExecution ["hexastack-cqrs"]
60
+ CBUS["CommandBusPort"]
61
+ QBUS["QueryBusPort"]
62
+ end
63
+
64
+ subgraph DecoupledProviders ["Decoupled Providers (via DI)"]
65
+ DB_FACTORY["sessionmaker / async_sessionmaker (from hexastack-db)"]
66
+ LOG_PORT["LoggerPort (from hexastack-logging)"]
67
+ end
68
+
69
+ HTTP --> APP
70
+ APP --> MW
71
+ MW --> ROUTER
72
+ ROUTER -->|dispatches to| CBUS
73
+ ROUTER -->|dispatches to| QBUS
74
+
75
+ MW -. consumes session factory from DI .-> DB_FACTORY
76
+ MW -. consumes LoggerPort from DI .-> LOG_PORT
77
+ ```
78
+
79
+ ### Explicit Dependencies (Direct)
80
+ - `hexastack-core`: DI container, core ports, exception registry, and context propagation.
81
+ - `hexastack-cqrs`: `CommandBusPort` and `QueryBusPort` for message dispatching.
82
+ - `fastapi>=0.141.1`: Web framework and ASGI routing.
83
+
84
+ ### Implied / Behavioral Relationships (DI-Mediated)
85
+ - **Zero-Dependency DB Session Management**: `DbSessionMiddleware` dynamically resolves SQLAlchemy `sessionmaker` from DI without directly importing `hexastack-db`.
86
+ - **Telemetry Integration**: `HttpLoggingMiddleware` outputs structured request telemetry through `LoggerPort`.
87
+ - **Exception Mapping**: Registers global exception handlers translating core domain errors into standard HTTP error responses.
88
+
89
+ ---
90
+
91
+ ## 4. Installation
92
+
93
+ ```bash
94
+ # Standalone install
95
+ pip install hexastack-fastapi
96
+
97
+ # With Uvicorn development server
98
+ pip install "hexastack-fastapi[web]" # or: pip install "hexastack[web]"
99
+
100
+ # Via umbrella package
101
+ pip install "hexastack[fastapi]"
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 5. Configuration Reference
107
+
108
+ ```toml
109
+ [hexastack.fastapi]
110
+ title = "Hexastack API"
111
+ version = "1.0.0"
112
+ docs_url = "/docs"
113
+ openapi_url = "/openapi.json"
114
+ cors_origins = ["*"]
115
+ enable_correlation_header = true
116
+ ```
117
+
118
+ ---
119
+
120
+ ## 6. Quickstart Example
121
+
122
+ ```python
123
+ from dataclasses import dataclass
124
+ from fastapi.testclient import TestClient
125
+ from hexastack_core.infra.bootstrap import bootstrap
126
+ from hexastack_cqrs.domain.query import Query
127
+ from hexastack_cqrs.infra.decorators import query_handler
128
+ from hexastack_fastapi.adapters.app import create_app
129
+
130
+
131
+ @dataclass(frozen=True)
132
+ class GetGreetingQuery(Query):
133
+ name: str
134
+
135
+
136
+ @query_handler(GetGreetingQuery)
137
+ class GetGreetingHandler:
138
+ def __call__(self, qry: GetGreetingQuery) -> dict:
139
+ return {"message": f"Hello, {qry.name}!"}
140
+
141
+
142
+ runtime = bootstrap(packages_to_scan=[__name__])
143
+ app = create_app(runtime)
144
+
145
+ client = TestClient(app)
146
+ response = client.get("/health")
147
+ print(response.json()) # {"status": "healthy"}
148
+ ```
@@ -0,0 +1,43 @@
1
+ [project]
2
+ name = "hexastack-fastapi"
3
+ version = "0.0.0"
4
+ description = "FastAPI presentation adapter for Hexastack"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ dependencies = [
8
+ "fastapi>=0.141.1",
9
+ "hexastack-core",
10
+ "hexastack-cqrs",
11
+ ]
12
+
13
+ [[project.authors]]
14
+ name = "Richard West"
15
+ email = "dopplereffect.us@gmail.com"
16
+
17
+ [project.optional-dependencies]
18
+ auth = ["hexastack-auth"]
19
+ docs = ["zensical>=0.0.56"]
20
+ testing = [
21
+ "playwright>=1.49.0",
22
+ "schemathesis>=3.39.0",
23
+ ]
24
+ ui = ["nicegui>=2.0.0"]
25
+
26
+ [project.entry-points."hexastack.bootstrappers"]
27
+ fastapi = "hexastack_fastapi.infra.bootstrap:FastApiBootstrapper"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.12.3,<0.13.0"]
31
+ build-backend = "uv_build"
32
+
33
+ [tool.uv.sources.hexastack-auth]
34
+ workspace = true
35
+
36
+ [tool.uv.sources.hexastack-core]
37
+ workspace = true
38
+
39
+ [tool.uv.sources.hexastack-cqrs]
40
+ workspace = true
41
+
42
+ [tool.importlinter]
43
+ root_packages = ["hexastack_fastapi"]
@@ -0,0 +1,44 @@
1
+ [project]
2
+ name = "hexastack-fastapi"
3
+ version = "0.0.0"
4
+ description = "FastAPI presentation adapter for Hexastack"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Richard West", email = "dopplereffect.us@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.13"
10
+ dependencies = [
11
+ "fastapi>=0.141.1",
12
+ "hexastack-core",
13
+ "hexastack-cqrs",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ auth = [
18
+ "hexastack-auth",
19
+ ]
20
+ docs = [
21
+ "zensical>=0.0.56",
22
+ ]
23
+ testing = [
24
+ "playwright>=1.49.0",
25
+ "schemathesis>=3.39.0",
26
+ ]
27
+ ui = [
28
+ "nicegui>=2.0.0",
29
+ ]
30
+
31
+ [project.entry-points."hexastack.bootstrappers"]
32
+ fastapi = "hexastack_fastapi.infra.bootstrap:FastApiBootstrapper"
33
+
34
+ [build-system]
35
+ requires = ["uv_build>=0.12.3,<0.13.0"]
36
+ build-backend = "uv_build"
37
+
38
+ [tool.uv.sources]
39
+ hexastack-auth = { workspace = true }
40
+ hexastack-core = { workspace = true }
41
+ hexastack-cqrs = { workspace = true }
42
+
43
+ [tool.importlinter]
44
+ root_packages = ["hexastack_fastapi"]
@@ -0,0 +1,6 @@
1
+ from hexastack_fastapi import adapters, infra
2
+
3
+ __all__ = [
4
+ "adapters",
5
+ "infra",
6
+ ]
@@ -0,0 +1,41 @@
1
+ from hexastack_fastapi.adapters.app import create_fastapi_app
2
+ from hexastack_fastapi.adapters.dependencies import (
3
+ check_openapi_conformance,
4
+ create_test_client,
5
+ get_container,
6
+ get_feature_flags,
7
+ get_pipeline,
8
+ require_feature,
9
+ )
10
+ from hexastack_fastapi.adapters.docs import (
11
+ DocumentationNotFoundError,
12
+ mount_zensical_docs,
13
+ )
14
+ from hexastack_fastapi.adapters.health import create_health_router
15
+ from hexastack_fastapi.adapters.routing import CqrsRouter
16
+ from hexastack_fastapi.adapters.ui import (
17
+ dispatch_command,
18
+ dispatch_query,
19
+ mount_devtools_dashboard,
20
+ mount_ui_app,
21
+ ui_page,
22
+ )
23
+
24
+ __all__ = [
25
+ "check_openapi_conformance",
26
+ "CqrsRouter",
27
+ "create_fastapi_app",
28
+ "create_health_router",
29
+ "create_test_client",
30
+ "dispatch_command",
31
+ "dispatch_query",
32
+ "DocumentationNotFoundError",
33
+ "get_container",
34
+ "get_feature_flags",
35
+ "get_pipeline",
36
+ "mount_devtools_dashboard",
37
+ "mount_ui_app",
38
+ "mount_zensical_docs",
39
+ "require_feature",
40
+ "ui_page",
41
+ ]
@@ -0,0 +1,118 @@
1
+ from contextlib import asynccontextmanager
2
+
3
+ from fastapi import FastAPI
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ from rodi import Container
6
+
7
+ from hexastack_core.infra.registries.exception import ExceptionRegistry
8
+ from hexastack_core.ports.logging import LoggingPort
9
+ from hexastack_cqrs.infra.pipeline import ExecutionPipeline
10
+ from hexastack_fastapi.adapters.docs import mount_zensical_docs
11
+ from hexastack_fastapi.adapters.health import create_health_router
12
+ from hexastack_fastapi.infra.config import HexastackFastApiConfig
13
+ from hexastack_fastapi.infra.exception_handlers import (
14
+ register_exception_handlers,
15
+ )
16
+ from hexastack_fastapi.infra.middleware.correlation import (
17
+ CorrelationHttpMiddleware,
18
+ )
19
+ from hexastack_fastapi.infra.middleware.logging import (
20
+ RequestLoggingHttpMiddleware,
21
+ )
22
+
23
+ __all__ = [
24
+ "create_fastapi_app",
25
+ ]
26
+
27
+
28
+ def create_fastapi_app(
29
+ config: HexastackFastApiConfig | None = None,
30
+ container: Container | None = None,
31
+ pipeline: ExecutionPipeline | None = None,
32
+ exception_registry: ExceptionRegistry | None = None,
33
+ ) -> FastAPI:
34
+ """Factory creating and configuring a FastAPI application integrated with Hexastack.
35
+
36
+ Notes/Architectural Intent:
37
+ Assembles FastAPI instance with OpenAPI documentation metadata, CORS middleware,
38
+ Correlation ID ASGI middleware, access logging, health check probes, Zensical docs mounting,
39
+ unified exception mapping, and DI container lifecycle management.
40
+
41
+ Args:
42
+ config: Optional HexastackFastApiConfig instance.
43
+ container: Optional rodi Container instance.
44
+ pipeline: Optional ExecutionPipeline instance.
45
+ exception_registry: Optional ExceptionRegistry for domain error mapping.
46
+
47
+ Returns:
48
+ Configured FastAPI application instance.
49
+
50
+ Raises:
51
+ None.
52
+ """
53
+ cfg = config or HexastackFastApiConfig()
54
+
55
+ @asynccontextmanager
56
+ async def lifespan(app: FastAPI):
57
+ yield
58
+ # Teardown background resources
59
+ if container is not None and LoggingPort in container:
60
+ logger = container.resolve(LoggingPort)
61
+ close_fn = getattr(logger, "close", None)
62
+ if callable(close_fn):
63
+ close_fn()
64
+
65
+ app = FastAPI(
66
+ title=cfg.title,
67
+ version=cfg.version,
68
+ description=cfg.description,
69
+ docs_url=cfg.docs_url,
70
+ redoc_url=cfg.redoc_url,
71
+ openapi_url=cfg.openapi_url,
72
+ lifespan=lifespan,
73
+ )
74
+
75
+ # Attach container and pipeline to application state
76
+ if container is not None:
77
+ app.state.container = container
78
+ if pipeline is not None:
79
+ app.state.pipeline = pipeline
80
+
81
+ # Attach CORS middleware if enabled
82
+ if cfg.cors.enable:
83
+ app.add_middleware(
84
+ CORSMiddleware,
85
+ allow_origins=cfg.cors.allow_origins,
86
+ allow_credentials=cfg.cors.allow_credentials,
87
+ allow_methods=cfg.cors.allow_methods,
88
+ allow_headers=cfg.cors.allow_headers,
89
+ )
90
+
91
+ # Attach request logging middleware if enabled
92
+ if cfg.logging.enable:
93
+ app.add_middleware(
94
+ RequestLoggingHttpMiddleware,
95
+ config=cfg,
96
+ container=container,
97
+ )
98
+
99
+ # Attach correlation middleware
100
+ app.add_middleware(CorrelationHttpMiddleware, config=cfg)
101
+
102
+ # Register unified exception handlers
103
+ register_exception_handlers(app, exception_registry=exception_registry)
104
+
105
+ # Mount health and readiness endpoints if enabled
106
+ if cfg.health.enable:
107
+ health_router = create_health_router(container=container, config=cfg.health)
108
+ app.include_router(health_router)
109
+
110
+ # Mount Zensical documentation site if enabled
111
+ if cfg.zensical.enable:
112
+ mount_zensical_docs(
113
+ app=app,
114
+ path=cfg.zensical.path,
115
+ site_dir=cfg.zensical.site_dir,
116
+ )
117
+
118
+ return app