"""Pydantic schemas for network diagrams.""" from datetime import datetime from uuid import UUID from pydantic import BaseModel, Field class Position(BaseModel): x: float y: float class DeviceProperties(BaseModel): hostname: str | None = None ip: str | None = None subnet: str | None = None vendor: str | None = None model: str | None = None role: str | None = None vlan: str | None = None notes: str | None = None status: str = Field(default="unknown", pattern=r"^(unknown|online|offline|degraded)$") class DiagramNode(BaseModel): id: str type: str label: str position: Position properties: DeviceProperties = Field(default_factory=DeviceProperties) class DiagramEdge(BaseModel): id: str source: str target: str label: str | None = None connectionType: str = "ethernet" speed: str | None = None notes: str | None = None routing: str | None = None class NetworkDiagramCreate(BaseModel): name: str = Field(min_length=1, max_length=255) client_name: str | None = None asset_name: str | None = None description: str | None = None nodes: list[DiagramNode] = Field(default_factory=list) edges: list[DiagramEdge] = Field(default_factory=list) class NetworkDiagramUpdate(BaseModel): name: str | None = Field(default=None, min_length=1, max_length=255) client_name: str | None = None asset_name: str | None = None description: str | None = None nodes: list[DiagramNode] | None = None edges: list[DiagramEdge] | None = None class NetworkDiagramResponse(BaseModel): id: UUID account_id: UUID name: str client_name: str | None = None asset_name: str | None = None description: str | None = None nodes: list[DiagramNode] = Field(default_factory=list) edges: list[DiagramEdge] = Field(default_factory=list) thumbnail_url: str | None = None is_archived: bool = False created_by: UUID | None = None created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class NetworkDiagramListItem(BaseModel): id: UUID name: str client_name: str | None = None description: str | None = None node_count: int = 0 category_counts: dict[str, int] = Field(default_factory=dict) created_by: UUID | None = None created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class ExistingBounds(BaseModel): minX: float maxX: float minY: float maxY: float class AIGenerateRequest(BaseModel): description: str = Field(min_length=1, max_length=5000) client_name: str | None = None mode: str = Field(default="replace", pattern=r"^(replace|merge)$") existingBounds: ExistingBounds | None = None class AIGenerateResponse(BaseModel): nodes: list[DiagramNode] edges: list[DiagramEdge] suggestedName: str | None = None notes: str | None = None class DiagramImportRequest(BaseModel): schemaVersion: int = Field(ge=1, le=1) name: str = Field(min_length=1, max_length=255) client_name: str | None = None description: str | None = None nodes: list[DiagramNode] = Field(default_factory=list) edges: list[DiagramEdge] = Field(default_factory=list) class DiagramImportResponse(BaseModel): diagram: NetworkDiagramResponse warnings: list[str] = Field(default_factory=list) class DiagramExportResponse(BaseModel): schemaVersion: int = 1 name: str client_name: str | None = None description: str | None = None nodes: list[DiagramNode] edges: list[DiagramEdge] exportedAt: str