import uuid from datetime import UTC, datetime from sqlalchemy import JSON, Boolean, DateTime, Integer, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from .db import Base def uid() -> str: return str(uuid.uuid4()) def now() -> datetime: return datetime.now(UTC) class ClientToken(Base): __tablename__ = "client_tokens" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uid) name: Mapped[str] = mapped_column(String(80)) app_key: Mapped[str] = mapped_column(String(80), index=True) token_hash: Mapped[str] = mapped_column(String(64), unique=True, index=True) allow_tags: Mapped[list[str]] = mapped_column(JSON, default=list) deny_tags: Mapped[list[str]] = mapped_column(JSON, default=list) active: Mapped[bool] = mapped_column(Boolean, default=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now) class CatalogItem(Base): __tablename__ = "catalog_items" __table_args__ = (UniqueConstraint("kind", "slug", "version", name="uq_catalog_version"),) id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uid) kind: Mapped[str] = mapped_column(String(24), index=True) slug: Mapped[str] = mapped_column(String(100), index=True) version: Mapped[int] = mapped_column(Integer, default=1) title: Mapped[str] = mapped_column(String(120)) description: Mapped[str] = mapped_column(Text, default="") tags: Mapped[list[str]] = mapped_column(JSON, default=list) definition: Mapped[dict] = mapped_column(JSON, default=dict) asset_url: Mapped[str | None] = mapped_column(Text) status: Mapped[str] = mapped_column(String(16), default="draft", index=True) sort_order: Mapped[int] = mapped_column(Integer, default=0) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now) class EditorProject(Base): __tablename__ = "editor_projects" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=uid) owner_id: Mapped[str] = mapped_column(String(80), index=True) source_type: Mapped[str] = mapped_column(String(40), default="custom") source_id: Mapped[str | None] = mapped_column(String(80), index=True) revision: Mapped[int] = mapped_column(Integer, default=1) document: Mapped[dict] = mapped_column(JSON) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=now, onupdate=now)