"""Nexus — Script & ScriptExecution Repository (Async SQLAlchemy)""" from typing import Optional, List, Tuple from sqlalchemy import select, func from sqlalchemy.ext.asyncio import AsyncSession from server.domain.models import Script, ScriptExecution class ScriptRepositoryImpl: def __init__(self, session: AsyncSession): self.session = session async def get_by_id(self, id: int) -> Optional[Script]: result = await self.session.execute(select(Script).where(Script.id == id)) return result.scalar_one_or_none() async def get_all(self) -> List[Script]: result = await self.session.execute(select(Script).order_by(Script.id)) return list(result.scalars().all()) async def get_by_category(self, category: str) -> List[Script]: result = await self.session.execute( select(Script).where(Script.category == category).order_by(Script.id) ) return list(result.scalars().all()) async def create(self, script: Script) -> Script: self.session.add(script) await self.session.commit() return script async def update(self, script: Script) -> Script: await self.session.commit() return script async def delete(self, id: int) -> bool: script = await self.get_by_id(id) if script: await self.session.delete(script) await self.session.commit() return True return False class ScriptExecutionRepositoryImpl: def __init__(self, session: AsyncSession): self.session = session async def get_by_id(self, id: int) -> Optional[ScriptExecution]: result = await self.session.execute( select(ScriptExecution).where(ScriptExecution.id == id) ) return result.scalar_one_or_none() async def create(self, execution: ScriptExecution) -> ScriptExecution: self.session.add(execution) await self.session.commit() return execution async def list_recent( self, limit: int = 50, offset: int = 0, status: Optional[str] = None, script_id: Optional[int] = None, ) -> Tuple[List[ScriptExecution], int]: filters = [] if status: filters.append(ScriptExecution.status == status) if script_id is not None: filters.append(ScriptExecution.script_id == script_id) count_stmt = select(func.count(ScriptExecution.id)) if filters: count_stmt = count_stmt.where(*filters) total = int((await self.session.execute(count_stmt)).scalar() or 0) stmt = select(ScriptExecution).order_by(ScriptExecution.started_at.desc()) if filters: stmt = stmt.where(*filters) result = await self.session.execute(stmt.limit(limit).offset(offset)) return list(result.scalars().all()), total async def update_status(self, id: int, status: str, results: str) -> Optional[ScriptExecution]: from datetime import datetime, timezone execution = await self.session.get(ScriptExecution, id) if execution: execution.status = status execution.results = results if status != "running" and execution.completed_at is None: execution.completed_at = datetime.now(timezone.utc) await self.session.commit() return execution