"""SQLAlchemy ORM models. This module defines the database ORM models that map to database tables. Models are used by repositories for data persistence. """ from __future__ import annotations from datetime import UTC, datetime from uuid import uuid4 from sqlalchemy import JSON, Boolean, DateTime, ForeignKey, Integer, String, Text from sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship Base = declarative_base() class PostORM(Base): # type: ignore[valid-type,misc] """SQLAlchemy model for Blog Post. Database table representation of blog posts. Maps to the 'posts' table with all post attributes. Attributes: id: Primary key as UUID string. title: Post title (max 200 chars). content: Post content (text). slug: URL-friendly unique identifier. author_id: Author reference. published: Publication status flag. tags: JSON array of tags. created_at: Creation timestamp. updated_at: Last update timestamp. Example: >>> post = PostORM(title="Post", content="...", slug="post", author_id="user-1") """ __tablename__ = "posts" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) title: Mapped[str] = mapped_column(String(200), nullable=False) content: Mapped[str] = mapped_column(Text, nullable=False) slug: Mapped[str] = mapped_column(String(200), nullable=False, unique=True, index=True) author_id: Mapped[str] = mapped_column(String(100), nullable=False, index=True) published: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, index=True) like_count: Mapped[int] = mapped_column(default=0, nullable=False) likes: Mapped[list[PostLikeORM]] = relationship( back_populates="post", cascade="all, delete-orphan" ) comments: Mapped[list[CommentORM]] = relationship( back_populates="post", cascade="all, delete-orphan" ) tags: Mapped[list[str]] = mapped_column(JSON, default=list) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), nullable=False, ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC), nullable=False, ) class PostLikeORM(Base): # type: ignore[valid-type,misc] """SQLAlchemy model for PostLike. Database table representation of post likes. Maps to the 'post_likes' table tracking which users/devices liked which posts. Attributes: id: Primary key as UUID string. post_id: Foreign key to the liked post. liked_by: User ID or device identifier. created_at: Creation timestamp. """ __tablename__ = "post_likes" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) post_id: Mapped[str] = mapped_column( String(36), ForeignKey("posts.id", ondelete="CASCADE"), nullable=False, index=True ) liked_by: Mapped[str] = mapped_column(String(200), nullable=False, index=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), nullable=False, ) post: Mapped[PostORM] = relationship(back_populates="likes") class CommentORM(Base): # type: ignore[valid-type,misc] """SQLAlchemy model for Comment. Database table representation of comments on blog posts. Maps to the 'comments' table with support for nested replies. Attributes: id: Primary key as UUID string. post_id: Foreign key to the parent post. author_id: Comment author reference. content: Comment text content (Markdown supported). parent_id: Optional foreign key to parent comment (replies). like_count: Number of likes on this comment. created_at: Creation timestamp. updated_at: Last update timestamp. """ __tablename__ = "comments" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) post_id: Mapped[str] = mapped_column( String(36), ForeignKey("posts.id", ondelete="CASCADE"), nullable=False, index=True ) author_id: Mapped[str] = mapped_column(String(100), nullable=False, index=True) content: Mapped[str] = mapped_column(Text, nullable=False) parent_id: Mapped[str | None] = mapped_column( String(36), ForeignKey("comments.id", ondelete="SET NULL"), nullable=True, index=True, ) like_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), nullable=False, ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC), nullable=False, ) post: Mapped[PostORM] = relationship(back_populates="comments") replies: Mapped[list[CommentORM]] = relationship( back_populates="parent", ) parent: Mapped[CommentORM | None] = relationship( back_populates="replies", remote_side="CommentORM.id", ) class CommentLikeORM(Base): # type: ignore[valid-type,misc] """SQLAlchemy model for CommentLike. Database table representation of comment likes. Maps to the 'comment_likes' table tracking which users liked which comments. Attributes: id: Primary key as UUID string. comment_id: Foreign key to the liked comment. liked_by: User identifier. created_at: Creation timestamp. """ __tablename__ = "comment_likes" id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid4())) comment_id: Mapped[str] = mapped_column( String(36), ForeignKey("comments.id", ondelete="CASCADE"), nullable=False, index=True, ) liked_by: Mapped[str] = mapped_column(String(200), nullable=False, index=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(UTC), nullable=False, )