models.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. from datetime import datetime
  2. from typing import Optional
  3. from sqlalchemy import BigInteger, DateTime, Enum, ForeignKey, JSON, SmallInteger, String, Text, func
  4. from sqlalchemy.orm import Mapped, mapped_column, relationship
  5. from .database import Base
  6. class Developer(Base):
  7. __tablename__ = "tpc_developers"
  8. id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
  9. name: Mapped[str] = mapped_column(String(128), nullable=False)
  10. email: Mapped[Optional[str]] = mapped_column(String(255))
  11. website: Mapped[Optional[str]] = mapped_column(String(512))
  12. avatar_url: Mapped[Optional[str]] = mapped_column(String(512))
  13. verified: Mapped[bool] = mapped_column(default=False, nullable=False)
  14. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
  15. updated_at: Mapped[datetime] = mapped_column(
  16. DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
  17. )
  18. apps: Mapped[list["App"]] = relationship(back_populates="developer")
  19. class Category(Base):
  20. __tablename__ = "tpc_categories"
  21. id: Mapped[int] = mapped_column(SmallInteger, primary_key=True, autoincrement=True)
  22. slug: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
  23. name: Mapped[str] = mapped_column(String(128), nullable=False)
  24. description: Mapped[Optional[str]] = mapped_column(String(255))
  25. icon: Mapped[Optional[str]] = mapped_column(String(64))
  26. sort_order: Mapped[int] = mapped_column(SmallInteger, default=0, nullable=False)
  27. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
  28. apps: Mapped[list["App"]] = relationship(secondary="tpc_app_category_map", back_populates="categories")
  29. class AppCategoryMap(Base):
  30. __tablename__ = "tpc_app_category_map"
  31. app_id: Mapped[int] = mapped_column(
  32. BigInteger, ForeignKey("tpc_apps.id", ondelete="CASCADE"), primary_key=True
  33. )
  34. category_id: Mapped[int] = mapped_column(
  35. SmallInteger, ForeignKey("tpc_categories.id", ondelete="CASCADE"), primary_key=True
  36. )
  37. class AppVersion(Base):
  38. __tablename__ = "tpc_app_versions"
  39. id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
  40. app_id: Mapped[int] = mapped_column(BigInteger, ForeignKey("tpc_apps.id", ondelete="CASCADE"), nullable=False)
  41. version: Mapped[str] = mapped_column(String(64), nullable=False)
  42. storage_url: Mapped[Optional[str]] = mapped_column(String(512))
  43. checksum_sha256: Mapped[Optional[str]] = mapped_column(String(64))
  44. size_bytes: Mapped[Optional[int]] = mapped_column(BigInteger)
  45. manifest: Mapped[Optional[dict]] = mapped_column(JSON)
  46. release_notes: Mapped[Optional[str]] = mapped_column(Text)
  47. min_client_version: Mapped[Optional[str]] = mapped_column(String(32))
  48. status: Mapped[str] = mapped_column(
  49. Enum("draft", "published", "yanked", name="version_status"),
  50. default="draft",
  51. nullable=False,
  52. )
  53. published_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
  54. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
  55. app: Mapped["App"] = relationship(back_populates="versions", foreign_keys=[app_id])
  56. class App(Base):
  57. __tablename__ = "tpc_apps"
  58. id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
  59. app_uid: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True)
  60. name: Mapped[str] = mapped_column(String(255), nullable=False)
  61. type: Mapped[str] = mapped_column(
  62. Enum("system", "community", "external", name="app_type"), nullable=False, index=True
  63. )
  64. developer_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("tpc_developers.id", ondelete="SET NULL"))
  65. icon_url: Mapped[Optional[str]] = mapped_column(String(512))
  66. short_description: Mapped[Optional[str]] = mapped_column(String(255))
  67. description: Mapped[Optional[str]] = mapped_column(Text)
  68. homepage_url: Mapped[Optional[str]] = mapped_column(String(512))
  69. current_version_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("tpc_app_versions.id"))
  70. status: Mapped[str] = mapped_column(
  71. Enum("draft", "published", "deprecated", "suspended", name="app_status"),
  72. default="draft",
  73. nullable=False,
  74. index=True,
  75. )
  76. is_featured: Mapped[bool] = mapped_column(default=False, nullable=False, index=True)
  77. download_count: Mapped[int] = mapped_column(BigInteger, default=0, nullable=False)
  78. publish_time: Mapped[Optional[datetime]] = mapped_column(DateTime, index=True)
  79. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), nullable=False)
  80. updated_at: Mapped[datetime] = mapped_column(
  81. DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
  82. )
  83. developer: Mapped[Optional["Developer"]] = relationship(back_populates="apps")
  84. categories: Mapped[list["Category"]] = relationship(secondary="tpc_app_category_map", back_populates="apps")
  85. versions: Mapped[list["AppVersion"]] = relationship(
  86. back_populates="app",
  87. foreign_keys="AppVersion.app_id",
  88. order_by="AppVersion.published_at.desc()",
  89. )
  90. current_version: Mapped[Optional["AppVersion"]] = relationship(
  91. foreign_keys=[current_version_id], lazy="joined"
  92. )