generator client { provider = "prisma-client" output = "../generated/prisma" } datasource db { provider = "postgresql" } // ============================================ // User & Auth // ============================================ model User { id String @id name String email String @unique emailVerified Boolean @default(false) image String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt displayUsername String? username String @unique bio String? accounts Account[] decks Deck[] deckFavorites DeckFavorite[] sessions Session[] followers Follow[] @relation("UserFollowers") following Follow[] @relation("UserFollowing") @@map("user") } model Session { id String @id expiresAt DateTime token String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt ipAddress String? userAgent String? userId String user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@map("session") } model Account { id String @id accountId String providerId String userId String accessToken String? refreshToken String? idToken String? accessTokenExpiresAt DateTime? refreshTokenExpiresAt DateTime? scope String? password String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@map("account") } model Verification { id String @id identifier String value String expiresAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([identifier]) @@map("verification") } // ============================================ // Deck & Card // ============================================ enum Visibility { PUBLIC PRIVATE } enum CardType { WORD PHRASE SENTENCE } model Deck { id Int @id @default(autoincrement()) name String desc String @db.Text @default("") userId String visibility Visibility @default(PRIVATE) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) cards Card[] favorites DeckFavorite[] @@index([userId]) @@index([visibility]) @@map("decks") } model Card { id Int @id @default(autoincrement()) deckId Int word String ipa String? queryLang String cardType CardType @default(WORD) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deck Deck @relation(fields: [deckId], references: [id], onDelete: Cascade) meanings CardMeaning[] @@index([deckId]) @@index([word]) @@map("cards") } model CardMeaning { id Int @id @default(autoincrement()) cardId Int partOfSpeech String? definition String example String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt card Card @relation(fields: [cardId], references: [id], onDelete: Cascade) @@index([cardId]) @@map("card_meanings") } model DeckFavorite { id Int @id @default(autoincrement()) userId String deckId Int createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id], onDelete: Cascade) deck Deck @relation(fields: [deckId], references: [id], onDelete: Cascade) @@unique([userId, deckId]) @@index([userId]) @@index([deckId]) @@map("deck_favorites") } // ============================================ // Social // ============================================ model Follow { id String @id @default(cuid()) followerId String @map("follower_id") followingId String @map("following_id") createdAt DateTime @default(now()) @map("created_at") follower User @relation("UserFollowers", fields: [followerId], references: [id], onDelete: Cascade) following User @relation("UserFollowing", fields: [followingId], references: [id], onDelete: Cascade) @@unique([followerId, followingId]) @@index([followerId]) @@index([followingId]) @@map("follows") }