generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" } enum UserRole { ADMIN EDITOR AUTHOR READER } enum ArticleStatus { DRAFT PUBLISHED ARCHIVED } model User { id String @id @default(uuid()) keycloakId String @unique email String @unique displayName String? avatarKey String? role UserRole @default(READER) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt articles Article[] comments Comment[] bookmarks Bookmark[] } model Category { id String @id @default(uuid()) name String slug String @unique parentId String? parent Category? @relation("CategoryTree", fields: [parentId], references: [id], onDelete: SetNull) children Category[] @relation("CategoryTree") articles ArticleCategory[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([parentId]) } model Tag { id String @id @default(uuid()) name String slug String @unique articles ArticleTag[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Article { id String @id @default(uuid()) title String slug String @unique content String @db.Text excerpt String? @db.Text status ArticleStatus @default(DRAFT) publishedAt DateTime? authorId String author User @relation(fields: [authorId], references: [id], onDelete: Cascade) categories ArticleCategory[] tags ArticleTag[] images ArticleImage[] comments Comment[] bookmarks Bookmark[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([status, publishedAt]) @@index([authorId]) } model ArticleCategory { articleId String categoryId String article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade) @@id([articleId, categoryId]) } model ArticleTag { articleId String tagId String article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade) @@id([articleId, tagId]) } model Image { id String @id @default(uuid()) fileKey String @unique articles ArticleImage[] createdAt DateTime @default(now()) } model ArticleImage { articleId String imageId String sortOrder Int @default(0) article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) image Image @relation(fields: [imageId], references: [id], onDelete: Cascade) @@id([articleId, imageId]) @@index([articleId, sortOrder]) } model Comment { id String @id @default(uuid()) content String @db.Text articleId String userId String parentId String? article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) parent Comment? @relation("CommentThread", fields: [parentId], references: [id], onDelete: Cascade) replies Comment[] @relation("CommentThread") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([articleId]) @@index([parentId]) } model Bookmark { userId String articleId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) article Article @relation(fields: [articleId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @@id([userId, articleId]) }