from __future__ import annotations import uuid from datetime import datetime from typing import Optional from sqlalchemy import Integer, String, Text, Boolean, DateTime, ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker class Base(DeclarativeBase): pass class Config(Base): __tablename__ = "configs" id: Mapped[int] = mapped_column(Integer, primary_key=True) name: Mapped[str] = mapped_column(String, nullable=False) token: Mapped[str] = mapped_column(String, unique=True, nullable=False) base_yaml: Mapped[str] = mapped_column(Text, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) updated_at: Mapped[datetime] = mapped_column( DateTime, default=datetime.utcnow, onupdate=datetime.utcnow ) subscriptions: Mapped[list["Subscription"]] = relationship( back_populates="config", cascade="all, delete-orphan" ) export_logs: Mapped[list["ExportLog"]] = relationship( back_populates="config", cascade="all, delete-orphan" ) class Subscription(Base): __tablename__ = "subscriptions" id: Mapped[int] = mapped_column(Integer, primary_key=True) config_id: Mapped[int] = mapped_column(Integer, ForeignKey("configs.id"), nullable=False) name: Mapped[str] = mapped_column(String, nullable=False) url: Mapped[str] = mapped_column(String, nullable=False) last_fetched_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) config: Mapped["Config"] = relationship(back_populates="subscriptions") class ExportLog(Base): __tablename__ = "export_logs" id: Mapped[int] = mapped_column(Integer, primary_key=True) config_id: Mapped[int] = mapped_column(Integer, ForeignKey("configs.id"), nullable=False) fetched_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) node_count: Mapped[int] = mapped_column(Integer, default=0) success: Mapped[bool] = mapped_column(Boolean, default=True) error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True) config: Mapped["Config"] = relationship(back_populates="export_logs") def make_engine(database_url: str): return create_async_engine(database_url) def make_session_factory(engine): return async_sessionmaker(engine, expire_on_commit=False)