"""The @client-decorated functions and the channel wire contracts every AFI backend registers. `register_fixture()` binds the functions into mizan_core.registry. The channel classes live in each backend's own app module — the `Channel` base is backend-specific — and bind the payload models below under `CHAT_CHANNEL` and `USER_ALERTS_CHANNEL`. """ from __future__ import annotations from pydantic import BaseModel from mizan_core.client.function import client from mizan_core.registry import register # ─── Output shapes ────────────────────────────────────────────────────────── class EchoOutput(BaseModel): message: str class WhoamiOutput(BaseModel): email: str authenticated: bool class ProfileOutput(BaseModel): user_id: int name: str class OrderOutput(BaseModel): id: int user_id: int total: int class StatusOutput(BaseModel): ok: bool # ─── Channel wire contracts ───────────────────────────────────────────────── CHAT_CHANNEL = "chat" USER_ALERTS_CHANNEL = "user_alerts" class ChatParams(BaseModel): room_id: str class ChatClientMessage(BaseModel): text: str class ChatServerMessage(BaseModel): text: str from_user: str class UserAlertsServerMessage(BaseModel): body: str unread: int # ─── Stored rows ──────────────────────────────────────────────────────────── _PROFILES = {5: "Ada Lovelace", 6: "Grace Hopper"} _ORDERS = [ OrderOutput(id=1, user_id=5, total=1200), OrderOutput(id=2, user_id=5, total=350), ] # ─── Fixture functions ────────────────────────────────────────────────────── @client def echo(request, text: str) -> EchoOutput: return EchoOutput(message=f"echo: {text}") @client def whoami(request) -> WhoamiOutput: return WhoamiOutput(email="anon@example.com", authenticated=False) @client(context="user") def user_profile(request, user_id: int) -> ProfileOutput: # A context member always answers, so an unstored id reads back under a # name derived from the id rather than an absence. return ProfileOutput( user_id=user_id, name=_PROFILES.get(user_id, f"user {user_id}") ) @client(context="user") def user_orders(request, user_id: int) -> list[OrderOutput]: return [order for order in _ORDERS if order.user_id == user_id] @client(affects="user") def update_profile(request, user_id: int, name: str) -> StatusOutput: return StatusOutput(ok=bool(name) and user_id in _PROFILES) @client def find_user(request, user_id: int) -> ProfileOutput | None: if user_id in _PROFILES: return ProfileOutput(user_id=user_id, name=_PROFILES[user_id]) return None @client(merge="user") def rename_user(request, user_id: int, name: str) -> ProfileOutput: # The merge target's return value is what the kernel splices into the # `user` context, so the renamed profile is the whole result. return ProfileOutput(user_id=user_id, name=name) # ─── Registration ─────────────────────────────────────────────────────────── def register_fixture() -> None: register(echo, "echo") register(whoami, "whoami") register(user_profile, "user_profile") register(user_orders, "user_orders") register(update_profile, "update_profile") register(find_user, "find_user") register(rename_user, "rename_user")