Coverage for src/lexigram/admin/di/sub_providers/core.py: 100%
33 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 14:56 +0800
1"""Admin core sub-provider — config, routing, Starlette sub-app, static files."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
7from lexigram.contracts.core.health import HealthCheckResult, HealthStatus
9if TYPE_CHECKING:
10 from lexigram.admin.config import AdminConfig
11 from lexigram.contracts.core.di import (
12 ContainerRegistrarProtocol,
13 ContainerResolverProtocol,
14 )
17class AdminCoreSubProvider:
18 """Manages core admin infrastructure: config, routing, templates, ASGI mounting.
20 This is a focused helper class, NOT a Provider subclass.
21 It is orchestrated by AdminProvider.
22 """
24 def __init__(self, config: AdminConfig, **kwargs: object) -> None:
25 self._config = config
26 self._kwargs = kwargs
27 self._mounted = False
29 @property
30 def config(self) -> AdminConfig:
31 """Return current admin config."""
32 return self._config
34 async def register(self, container: ContainerRegistrarProtocol) -> None:
35 """Register core admin services: config, routing, rendering, feature flags."""
36 from lexigram.admin.config import AdminConfig
37 from lexigram.admin.core.rendering import AdminRenderer
38 from lexigram.admin.engine.renderer import AdminRenderer as EngineAdminRenderer
39 from lexigram.admin.services.feature_flags import AdminFeatureFlagService
40 from lexigram.admin.settings.panel.registry import ConfigRegistry
41 from lexigram.admin.state.dependency_tracker import DependencyTracker
43 container.singleton(AdminConfig, self._config)
45 # AdminRouter is built in AdminProvider.mount_to_app() with the
46 # resolved resource and controller instances — do NOT register as class here
47 # (its constructor has resources/controllers that are not container-resolvable).
49 # Register the engine AdminRenderer (all-optional deps) — this is what
50 # AdminController subclasses use for rendering admin pages.
51 from lexigram.admin.engine.renderer import AdminRendererConfig
53 renderer_config = AdminRendererConfig(
54 primary_color=self._config.ui.primary_color or "#6b7280",
55 )
56 container.singleton(EngineAdminRenderer, EngineAdminRenderer(renderer_config))
58 # Register the core AdminRenderer as well (used internally)
59 container.singleton(AdminRenderer, AdminRenderer)
61 container.singleton(DependencyTracker, DependencyTracker)
62 container.singleton(ConfigRegistry, ConfigRegistry.with_defaults)
64 # Feature flags: register the admin service only.
65 # The concrete FlagManagerProtocol implementation is expected to be
66 # registered by the application's feature-flags provider.
67 container.singleton(AdminFeatureFlagService, AdminFeatureFlagService)
69 async def boot(self, container: ContainerResolverProtocol) -> None:
70 """Initialize Starlette sub-app and mount routes."""
71 self._mounted = True
73 async def shutdown(self) -> None:
74 """Clean up core resources."""
75 self._mounted = False
77 async def health_check(self, timeout: float = 5.0) -> HealthCheckResult:
78 """Return core health status."""
79 return HealthCheckResult(
80 component="admin_core",
81 status=HealthStatus.HEALTHY if self._mounted else HealthStatus.UNKNOWN,
82 message="Admin core operational" if self._mounted else "Not yet mounted",
83 )
86__all__ = ["AdminCoreSubProvider"]