/** * This is the Prisma schema file for the application. It defines the data models, their relationships, and the database configuration. * The schema is used by Prisma to generate the database migrations and the Prisma Client for querying the database. */ /** * ---------------------------------- * Prisma Schema Configuration * ---------------------------------- */ generator client { provider = "prisma-client-js" } generator dbml { provider = "prisma-dbml-generator" } datasource db { provider = "postgresql" } /** * ---------------------------------- * Enum Definitions * ---------------------------------- */ enum user_role { user contributor curator admin } enum user_sex { male female } enum auth_provider { google github } enum device_type { mobile tablet desktop unknown } enum user_preference_state { exclude include } enum media_season { winter spring summer fall } enum character_role { main supporting background } enum status_submission { pending approved rejected } enum like_type { like dislike } enum audit_action { delete restore edit flag } enum privacy_level { public unlisted private } enum collection_access_level { owner moderator contributor viewer } /** * ---------------------------------- * Model for User and related entities * ---------------------------------- */ model User { id String @id @default(uuid(7)) @db.Uuid email String @unique password String? @db.VarChar(255) username String @unique @db.VarChar(28) fullname String @db.VarChar(32) avatar String? @db.VarChar(255) bio String? @db.Text datebirth DateTime? @db.Date role user_role @default(user) sex user_sex? phone_number String? @db.VarChar(20) country Country? @relation(fields: [countryId], references: [id], name: "UserCountry") address UserAddress? preferences UserPreference? created_at DateTime @default(now()) @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() deleted_at DateTime? @db.Timestamptz() countryId String? @db.Uuid oauth_accounts UserOauthAccounts[] sessions UserSession[] followers UserFollow[] @relation("UserFollowFollowing") following UserFollow[] @relation("UserFollowFollower") provisioned_as_admin ProvisionedUser[] @relation("ProvisionedUserAdmin") provisioned_as_user ProvisionedUser[] @relation("ProvisionedUserUser") created_producers Producer[] submitted_media MediaSubmission[] @relation("MediaSubmissionSubmitter") reviewed_media MediaSubmission[] @relation("MediaSubmissionReviewer") updated_media Media[] @relation("MediaUpdater") deleted_media Media[] @relation("MediaDeleter") created_episodes Episode[] submitted_videos VideoSubmission[] @relation("VideoSubmissionSubmitter") reviewed_videos VideoSubmission[] @relation("VideoSubmissionReviewer") submitted_video_services VideoServiceSubmission[] @relation("VideoServiceSubmissionSubmitter") reviewed_video_services VideoServiceSubmission[] @relation("VideoServiceSubmissionReviewer") comments Comment[] comment_likes CommentLike[] comment_audit_logs CommentAuditLog[] comment_reports CommentReport[] home_media_banners HomeMediaBanner[] watch_histories UserWatchHistory[] saved_collections CollectionMember[] @relation("CollectionMemberUser") invited_collections CollectionMember[] @relation("CollectionMemberInviter") contributed_collections MediaCollection[] @relation("MediaCollectionAdder") @@index([email]) @@index([username]) @@map("users") } model UserAddress { user_id String @id @db.Uuid address String @db.VarChar(255) district String @db.VarChar(100) city String @db.VarChar(100) province String @db.VarChar(100) postal_code String @db.VarChar(20) coordinate String? @db.VarChar(50) updated_at DateTime @updatedAt @db.Timestamptz() user User @relation(fields: [user_id], references: [id]) @@map("user_addresses") } model UserOauthAccounts { id String @id @default(uuid(7)) @db.Uuid user User @relation(fields: [user_id], references: [id]) provider_name auth_provider provider_sub String? @db.VarChar(255) provider_email String? @db.VarChar(255) provider_token String? @db.Text refresh_token String? @db.Text expires_at DateTime? @db.Timestamptz() created_at DateTime @default(now()) @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() user_id String @db.Uuid @@map("user_oauth_accounts") } model UserSession { id String @id @default(uuid(7)) @db.Uuid user User @relation(fields: [user_id], references: [id]) device_type device_type os_type String? @db.VarChar(50) os_version String? @db.VarChar(50) browser_name String? @db.VarChar(50) browser_version String? @db.VarChar(50) ip_login String? @db.Inet() valid_until DateTime @db.Timestamptz() login_at DateTime @default(now()) @db.Timestamptz() logout_at DateTime? @db.Timestamptz() user_id String @db.Uuid @@map("user_sessions") } model UserPreference { user User @relation(fields: [user_id], references: [id]) char_as_partner Character? @relation(fields: [char_as_partner_id], references: [id]) comment_picture String? @db.VarChar(255) enable_watch_history Boolean @default(true) enable_search_history Boolean @default(false) is_private_account Boolean @default(false) can_message_me Boolean @default(true) publish_birthday Boolean @default(false) publish_email Boolean @default(false) publish_phone_number Boolean @default(false) publish_country Boolean @default(false) publish_partner Boolean @default(true) subscribe_to_newsletter Boolean @default(true) enable_security_alerts Boolean @default(true) genre_preferences UserGenrePreference[] rating_preferences UserRatingPreference[] country_preferences UserCountryPreference[] user_id String @id @db.Uuid char_as_partner_id String? @db.Uuid @@map("user_preferences") } model UserGenrePreference { user UserPreference @relation(fields: [user_id], references: [user_id]) genre Genre @relation(fields: [genre_id], references: [id]) state user_preference_state user_id String @db.Uuid genre_id String @db.Uuid @@id([user_id, genre_id]) @@map("user_genre_preferences") } model UserRatingPreference { user UserPreference @relation(fields: [user_id], references: [user_id]) rating MediaAgeRating @relation(fields: [rating_id], references: [id]) state user_preference_state user_id String @db.Uuid rating_id String @db.Uuid @@id([user_id, rating_id]) @@map("user_rating_preferences") } model UserCountryPreference { user UserPreference @relation(fields: [user_id], references: [user_id]) country Country @relation(fields: [country_id], references: [id]) state user_preference_state user_id String @db.Uuid country_id String @db.Uuid @@id([user_id, country_id]) @@map("user_country_preferences") } model UserFollow { follower User @relation("UserFollowFollower", fields: [follower_id], references: [id]) following User @relation("UserFollowFollowing", fields: [following_id], references: [id]) created_at DateTime @default(now()) @db.Timestamptz() follower_id String @db.Uuid following_id String @db.Uuid @@id([follower_id, following_id]) @@map("user_follows") } model UserWatchHistory { user User @relation(fields: [user_id], references: [id]) episode Episode @relation(fields: [episode_number, media_id], references: [episode_number, media_id]) updated_at DateTime @updatedAt @db.Timestamptz() user_id String @db.Uuid episode_number Int @db.SmallInt media_id String @db.Uuid @@id([user_id, episode_number, media_id]) @@map("user_watch_histories") } model Collection { id String @id @default(uuid(7)) @db.Uuid name String @db.VarChar(64) code String? @db.VarChar(12) cover_url String? @db.VarChar(255) privacy privacy_level @default(private) created_at DateTime @default(now()) @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() saved_media MediaCollection[] members CollectionMember[] @@map("collections") } model CollectionMember { collection Collection @relation(fields: [collection_id], references: [id]) user User @relation(fields: [user_id], references: [id], name: "CollectionMemberUser") access_level collection_access_level invited_by User? @relation(fields: [invited_by_id], references: [id], name: "CollectionMemberInviter") invited_at DateTime? @db.Timestamptz() collection_id String @db.Uuid user_id String @db.Uuid invited_by_id String? @db.Uuid @@id([collection_id, user_id]) @@map("collection_members") } /** * ---------------------------------- * Model for Media and related entities * ---------------------------------- */ model Media { id String @id @default(uuid(7)) @db.Uuid mal_id Int @unique title String @db.VarChar(255) title_secondary String? @db.VarChar(255) title_original String? @db.VarChar(255) title_synonyms String[] @db.VarChar(255) trailer MediaTrailer? synopsis String? @db.Text small_image_url String? @db.VarChar(255) medium_image_url String @db.VarChar(255) large_image_url String? @db.VarChar(255) type MediaType @relation(fields: [type_id], references: [id]) source MediaSource? @relation(fields: [source_id], references: [id]) status MediaStatus? @relation(fields: [status_id], references: [id]) airing Boolean start_airing DateTime? @db.Date end_airing DateTime? @db.Date age_rating MediaAgeRating? @relation(fields: [age_rating_id], references: [id]) score Decimal? @db.Decimal(2, 2) score_total Int @default(0) score_count Int @default(0) background String? @db.Text season media_season year Int? @db.SmallInt country Country? @relation(fields: [country_id], references: [id]) broadcast_day String? @db.VarChar(20) producers MediaProducer[] licensors MediaLicensor[] studios MediaStudio[] genres MediaGenre[] explicit_genres MediaExplicitGenre[] themes MediaTheme[] demographics MediaDemographic[] relations MediaRelation[] @relation("MediaRelationMedia") external_links MediaExternalLink[] characters MediaCharacter[] submissions MediaSubmission? created_at DateTime @default(now()) @db.Timestamptz() updated_by User? @relation(fields: [updated_by_id], references: [id], name: "MediaUpdater") updated_at DateTime @updatedAt @db.Timestamptz() deleted_by User? @relation(fields: [deleted_by_id], references: [id], name: "MediaDeleter") deleted_at DateTime? @db.Timestamptz() type_id String @db.Uuid source_id String @db.Uuid status_id String @db.Uuid age_rating_id String? @db.Uuid country_id String? @db.Uuid related_media MediaRelation[] @relation("MediaRelationRelatedMedia") updated_by_id String? @db.Uuid deleted_by_id String? @db.Uuid episodes Episode[] home_media_banners HomeMediaBanner[] saved_to_collections MediaCollection[] @@map("medias") } model MediaSubmission { id String @id @default(uuid(7)) @db.Uuid media Media @relation(fields: [media_id], references: [id]) submitter User @relation(fields: [submitter_id], references: [id], name: "MediaSubmissionSubmitter") status status_submission @default(pending) reviewer User? @relation(fields: [reviewer_id], references: [id], name: "MediaSubmissionReviewer") reviewed_at DateTime? @db.Timestamptz() reason String? @db.Text created_at DateTime @default(now()) @db.Timestamptz() media_id String @unique @db.Uuid submitter_id String @db.Uuid reviewer_id String? @db.Uuid @@map("media_submissions") } model MediaCollection { media Media @relation(fields: [media_id], references: [id]) collection Collection @relation(fields: [collection_id], references: [id]) added_by User @relation(fields: [added_by_id], references: [id], name: "MediaCollectionAdder") added_at DateTime @default(now()) @db.Timestamptz() media_id String @db.Uuid collection_id String @db.Uuid added_by_id String @db.Uuid @@id([media_id, collection_id]) @@map("media_collections") } model MediaTrailer { media_id String @id @db.Uuid url String? @db.VarChar(255) embed_url String? @unique @db.VarChar(255) small_image_url String? @db.VarChar(255) large_image_url String? @db.VarChar(255) maximum_image_url String? @db.VarChar(255) media Media @relation(fields: [media_id], references: [id]) @@map("media_trailers") } model MediaType { id String @id @default(uuid(7)) @db.Uuid name String @unique @db.VarChar(100) Media Media[] @@map("media_types") } model MediaSource { id String @id @default(uuid(7)) @db.Uuid name String @unique @db.VarChar(100) media Media[] @@map("media_sources") } model MediaStatus { id String @id @default(uuid(7)) @db.Uuid name String @unique @db.VarChar(100) media Media[] @@map("media_statuses") } model MediaAgeRating { id String @id @default(uuid(7)) @db.Uuid name String @unique @db.VarChar(100) min_age Int @db.SmallInt media Media[] user_rating_preferences UserRatingPreference[] @@map("media_age_ratings") } model MediaProducer { media Media @relation(fields: [media_id], references: [id]) producer Producer @relation(fields: [producer_id], references: [id]) media_id String @db.Uuid producer_id String @db.Uuid @@id([media_id, producer_id]) @@map("media_producers") } model MediaLicensor { media Media @relation(fields: [media_id], references: [id]) licensor Producer @relation(fields: [licensor_id], references: [id]) media_id String @db.Uuid licensor_id String @db.Uuid @@id([media_id, licensor_id]) @@map("media_licensors") } model MediaStudio { media Media @relation(fields: [media_id], references: [id]) studio Producer @relation(fields: [studio_id], references: [id]) media_id String @db.Uuid studio_id String @db.Uuid @@id([media_id, studio_id]) @@map("media_studios") } model Producer { id String @id @default(uuid(7)) @db.Uuid mal_id Int @unique type String @db.VarChar(24) name String @db.VarChar(255) url String? @db.VarChar(255) created_by User @relation(fields: [created_by_id], references: [id]) created_at DateTime @default(now()) @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() deleted_at DateTime? @db.Timestamptz() created_by_id String @db.Uuid media_producers MediaProducer[] media_licensors MediaLicensor[] media_studios MediaStudio[] @@map("producers") } model MediaGenre { media Media @relation(fields: [media_id], references: [id]) genre Genre @relation(fields: [genre_id], references: [id]) media_id String @db.Uuid genre_id String @db.Uuid @@id([media_id, genre_id]) @@map("media_genres") } model MediaExplicitGenre { media Media @relation(fields: [media_id], references: [id]) genre Genre @relation(fields: [genre_id], references: [id]) media_id String @db.Uuid genre_id String @db.Uuid @@id([media_id, genre_id]) @@map("media_explicit_genres") } model MediaTheme { media Media @relation(fields: [media_id], references: [id]) theme Genre @relation(fields: [genre_id], references: [id]) media_id String @db.Uuid genre_id String @db.Uuid @@id([media_id, genre_id]) @@map("media_themes") } model MediaDemographic { media Media @relation(fields: [media_id], references: [id]) demographic Genre @relation(fields: [demographic_id], references: [id]) media_id String @db.Uuid demographic_id String @db.Uuid @@id([media_id, demographic_id]) @@map("media_demographics") } model Genre { id String @id @default(uuid(7)) @db.Uuid mal_id Int @unique @db.SmallInt name String @db.VarChar(100) slug String @db.VarChar(115) thumbnail_url String? @db.VarChar(255) media_genres MediaGenre[] media_explicit_genres MediaExplicitGenre[] media_themes MediaTheme[] media_demographics MediaDemographic[] user_genre_preferences UserGenrePreference[] @@map("genres") } model MediaRelation { media Media @relation(fields: [media_id], references: [id], name: "MediaRelationMedia") related_media Media @relation(fields: [related_media_id], references: [id], name: "MediaRelationRelatedMedia") relation_type String @db.VarChar(50) media_id String @db.Uuid related_media_id String @db.Uuid @@id([media_id, related_media_id]) @@map("media_relations") } model MediaExternalLink { id String @id @default(uuid(7)) @db.Uuid media Media @relation(fields: [media_id], references: [id]) url String @db.VarChar(255) site_name String? @db.VarChar(100) media_id String @db.Uuid @@map("media_external_links") } model MediaCharacter { media Media @relation(fields: [media_id], references: [id]) character Character @relation(fields: [character_id], references: [id]) voice_actors VoiceActor[] role character_role media_id String @db.Uuid character_id String @db.Uuid @@id([character_id, media_id]) @@map("media_characters") } model Character { id String @id @default(uuid(7)) @db.Uuid name String @db.VarChar(255) image String? @db.VarChar(255) small_image String? @db.VarChar(255) mal_id Int? @unique fanpage_url String? @db.VarChar(255) liked Int @default(0) deleted_at DateTime? @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() created_at DateTime @default(now()) @db.Timestamptz() partnered_user UserPreference[] media_characters MediaCharacter[] @@map("characters") } model VoiceActor { id String @id @default(uuid(7)) @db.Uuid language String @db.VarChar(115) actor_staff Staff @relation(fields: [staff_id], references: [id]) staff_id String @db.Uuid media_id String @db.Uuid character_id String @db.Uuid media_character MediaCharacter @relation(fields: [media_id, character_id], references: [media_id, character_id]) @@unique([media_id, character_id, staff_id, language]) @@map("voice_actors") } model Staff { id String @id @default(uuid(7)) @db.Uuid name String @db.VarChar(255) image String? @db.VarChar(255) mal_id Int? @unique deleted_at DateTime? @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() created_at DateTime @default(now()) @db.Timestamptz() voice_actors VoiceActor[] @@map("staff") } model Episode { episode_number Int @db.SmallInt mal_url String? @db.VarChar(255) forum_url String? @db.VarChar(255) title String @db.VarChar(155) title_origin String? @db.VarChar(155) title_romanji String? @db.VarChar(155) aired_at DateTime? @db.Date filler Boolean recap Boolean total_score Int @default(0) score_count Int @default(0) deleted_at DateTime? @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() created_at DateTime @default(now()) @db.Timestamptz() created_by User @relation(fields: [created_by_id], references: [id]) videos Video[] created_by_id String @db.Uuid comments Comment[] watch_histories UserWatchHistory[] media Media @relation(fields: [media_id], references: [id]) media_id String @db.Uuid @@id([media_id, episode_number]) @@map("episodes") } model Video { id String @id @default(uuid(7)) @db.Uuid video_service VideoService @relation(fields: [video_service_id], references: [id]) episode Episode @relation(fields: [episode_number, media_id], references: [episode_number, media_id]) priority Int? @db.SmallInt video_code String @db.VarChar(255) short_code String? @db.VarChar(255) thumbnail_code String? @db.VarChar(255) download_code String? @db.VarChar(255) created_at DateTime @default(now()) @db.Timestamptz() deleted_at DateTime? @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() episode_number Int @db.SmallInt media_id String @db.Uuid created_by_id String @db.Uuid video_submission VideoSubmission? video_service_id String @db.Uuid @@unique([media_id, episode_number, priority]) @@map("videos") } model VideoSubmission { video_id String @id @db.Uuid created_by User @relation(fields: [created_by_id], references: [id], name: "VideoSubmissionSubmitter") reviewer User? @relation(fields: [reviewer_id], references: [id], name: "VideoSubmissionReviewer") status status_submission @default(pending) reviewed_at DateTime? @db.Timestamptz() reason String? @db.Text created_at DateTime @default(now()) @db.Timestamptz() created_by_id String @db.Uuid reviewer_id String? @db.Uuid video Video @relation(fields: [video_id], references: [id]) @@map("video_submissions") } model VideoService { id String @id @default(uuid(7)) @db.Uuid name String @db.VarChar(155) resolution Int @db.SmallInt domain String @db.VarChar(255) image_url String? @db.VarChar(255) hex_color String? @db.VarChar(10) endpoint_video String @db.VarChar(255) endpoint_short String? @db.VarChar(255) endpoint_image String? @db.VarChar(255) endpoint_download String? @db.VarChar(255) deleted_at DateTime? @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() created_at DateTime @default(now()) @db.Timestamptz() videos Video[] video_service_submissions VideoServiceSubmission? @@unique([name, resolution]) @@map("video_services") } model VideoServiceSubmission { video_service_id String @id @db.Uuid created_by User @relation(fields: [created_by_id], references: [id], name: "VideoServiceSubmissionSubmitter") status status_submission @default(pending) reviewer User? @relation(fields: [reviewer_id], references: [id], name: "VideoServiceSubmissionReviewer") reviewed_at DateTime? @db.Timestamptz() reason String? @db.Text created_at DateTime @default(now()) @db.Timestamptz() video_service VideoService @relation(fields: [video_service_id], references: [id]) created_by_id String @db.Uuid reviewer_id String? @db.Uuid @@map("video_service_submissions") } model Comment { id String @id @default(uuid(7)) @db.Uuid user User @relation(fields: [user_id], references: [id]) episode Episode @relation(fields: [episode_number, media_id], references: [episode_number, media_id]) content String @db.Text created_at DateTime @default(now()) @db.Timestamptz() updated_at DateTime @updatedAt @db.Timestamptz() deleted_at DateTime? @db.Timestamptz() user_id String @db.Uuid episode_number Int @db.SmallInt media_id String @db.Uuid likes CommentLike[] audit_logs CommentAuditLog[] reports CommentReport[] @@map("comments") } model CommentLike { user_id String @db.Uuid comment_id String @db.Uuid type like_type created_at DateTime @default(now()) @db.Timestamptz() user User @relation(fields: [user_id], references: [id]) comment Comment @relation(fields: [comment_id], references: [id]) @@id([user_id, comment_id]) @@map("comment_likes") } model CommentAuditLog { id String @id @default(uuid(7)) @db.Uuid comment Comment @relation(fields: [comment_id], references: [id]) performed_by User @relation(fields: [performed_by_id], references: [id]) action audit_action created_at DateTime @default(now()) @db.Timestamptz() comment_id String @db.Uuid performed_by_id String @db.Uuid @@map("comment_audit_logs") } model CommentReport { id String @id @default(uuid(7)) @db.Uuid reporter User @relation(fields: [reporter_id], references: [id]) comment Comment @relation(fields: [comment_id], references: [id]) title String @db.VarChar(115) status status_submission description String? @db.Text reported_at DateTime @default(now()) @db.Timestamptz() closed_at DateTime? @db.Timestamptz() reporter_id String @db.Uuid comment_id String @db.Uuid @@map("comment_reports") } /** * ---------------------------------- * Model for System Apps and related entities * ---------------------------------- */ model ProvisionedUser { provisioned_by User @relation(fields: [admin_id], references: [id], name: "ProvisionedUserAdmin") provisioned_to User @relation(fields: [user_id], references: [id], name: "ProvisionedUserUser") provisioned_at DateTime @default(now()) @db.Timestamptz() reason String? @db.VarChar(255) admin_id String @db.Uuid user_id String @db.Uuid @@id([admin_id, user_id]) @@map("provisioned_users") } model Country { id String @id @default(uuid(7)) @db.Uuid name String @db.VarChar(155) slug String @db.VarChar(165) code String @unique @db.VarChar(3) flag String? @db.VarChar(255) banner String? @db.VarChar(255) UserCountry User[] @relation("UserCountry") UserCountryPreference UserCountryPreference[] Media Media[] @@map("countries") } model HomeMediaBanner { id String @id @default(uuid(7)) @db.Uuid media Media @relation(fields: [media_id], references: [id]) created_by User @relation(fields: [created_by_id], references: [id]) priority Int @unique @db.SmallInt start_show DateTime @db.Date end_show DateTime @db.Date created_at DateTime @default(now()) @db.Timestamptz() media_id String @db.Uuid created_by_id String @db.Uuid @@map("home_media_banners") }