"""Built-in, service-less widget kinds. These widgets do not talk to an external service and therefore have no ``service_id``. They are kept out of the service registry (which models configurable external services) and live here as a small closed set. Currently: ``backups`` (reads the internal backup tables) and ``static`` (plain text/markdown). """ from __future__ import annotations from typing import Any from media_library_viewer_api.integrations.base import WidgetKind BUILTIN_WIDGET_KINDS: dict[str, WidgetKind] = { "backups": WidgetKind( kind="backups", name="Backups", description="Backup job summary and active alerts.", config_schema={"type": "object", "properties": {}, "required": []}, default_config={}, refresh_interval_ms=60_000, ), "static": WidgetKind( kind="static", name="Static text", description="Plain text or markdown note.", config_schema={ "type": "object", "properties": {"text": {"type": "string", "description": "Text or markdown content"}}, "required": ["text"], }, default_config={"text": ""}, refresh_interval_ms=0, ), } def get_builtin_widget_kind(kind: str) -> WidgetKind | None: return BUILTIN_WIDGET_KINDS.get(kind) def is_builtin_kind(kind: str) -> bool: return kind in BUILTIN_WIDGET_KINDS def builtin_widget_kind_models() -> dict[str, type]: """Pydantic widget-config models for built-in kinds (validated manually). Backups has no user fields; static validates ``text``. """ from pydantic import BaseModel, Field class StaticConfig(BaseModel): text: str = Field(default="") return {"static": StaticConfig} def validate_builtin_config(kind: str, config: dict[str, Any]) -> dict[str, Any]: """Validate (lightly) a built-in widget config and return the cleaned dict.""" models = builtin_widget_kind_models() model_cls = models.get(kind) if model_cls is None: return dict(config or {}) return model_cls.model_validate(config or {}).model_dump(exclude_none=True)