feat(02-01): add 8 Prisma models, 3 enums, Pet back-relations
- Append PostType, MilestoneType (16 values), ReportReason enums - Add Post, PostImage, Milestone, Story, StoryView, Follow, Block, Report models - Add Pet back-relations for all Phase 2 social graph relations - Explicit named relations on all self-referential models (Follower/Followee, Blocker/Blocked, StoryViewer, Reporter) - StoryView.storyId has NO onDelete cascade per D-08 (views survive story expiry) - npx prisma validate + generate + db push all succeeded
This commit is contained in:
1 parent
ff6b48e3aa
commit
b2db6310fe
1 file changed
+141
-1
+141
-1
@@ -40,9 +40,149 @@ model Pet {
|
||||
name String
|
||||
bio String?
|
||||
adoptionStory String?
|
||||
avatarKey String? // R2 object key, NOT a full URL
|
||||
avatarKey String? // Supabase Storage object key, NOT a full URL
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Phase 2 back-relations
|
||||
posts Post[]
|
||||
stories Story[]
|
||||
storyViews StoryView[] @relation("StoryViewer")
|
||||
following Follow[] @relation("Follower")
|
||||
followers Follow[] @relation("Followee")
|
||||
blocking Block[] @relation("Blocker")
|
||||
blockedBy Block[] @relation("Blocked")
|
||||
reports Report[] @relation("Reporter")
|
||||
|
||||
@@index([ownerId])
|
||||
}
|
||||
|
||||
// ─── Phase 2 Enums ───────────────────────────────────────────────────────────
|
||||
|
||||
enum PostType {
|
||||
PHOTO
|
||||
MILESTONE
|
||||
}
|
||||
|
||||
enum MilestoneType {
|
||||
BIRTHDAY
|
||||
ADOPTION_DAY
|
||||
FIRST_OUTING
|
||||
VET_VISIT
|
||||
LITTER
|
||||
FOLLOWERS_500
|
||||
FOLLOWERS_1K
|
||||
FOLLOWERS_2_5K
|
||||
FOLLOWERS_5K
|
||||
FOLLOWERS_10K
|
||||
FOLLOWERS_25K
|
||||
FOLLOWERS_50K
|
||||
FOLLOWERS_100K
|
||||
FOLLOWERS_250K
|
||||
FOLLOWERS_500K
|
||||
FOLLOWERS_1M
|
||||
}
|
||||
|
||||
enum ReportReason {
|
||||
SPAM
|
||||
HARASSMENT
|
||||
INAPPROPRIATE
|
||||
MISINFORMATION
|
||||
OTHER
|
||||
}
|
||||
|
||||
// ─── Phase 2 Models ──────────────────────────────────────────────────────────
|
||||
|
||||
model Post {
|
||||
id String @id @default(cuid())
|
||||
pet Pet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
||||
petId String
|
||||
type PostType @default(PHOTO)
|
||||
caption String? @db.VarChar(500)
|
||||
images PostImage[]
|
||||
milestone Milestone?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([petId, createdAt(sort: Desc)])
|
||||
}
|
||||
|
||||
model PostImage {
|
||||
id String @id @default(cuid())
|
||||
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||
postId String
|
||||
storageKey String // Supabase Storage object key
|
||||
position Int // 0-based order in carousel
|
||||
width Int?
|
||||
height Int?
|
||||
|
||||
@@unique([postId, position])
|
||||
@@index([postId])
|
||||
}
|
||||
|
||||
model Milestone {
|
||||
id String @id @default(cuid())
|
||||
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
|
||||
postId String @unique
|
||||
milestoneType MilestoneType
|
||||
notes String? @db.VarChar(500) // free text for 'litter' type (D-09)
|
||||
}
|
||||
|
||||
model Story {
|
||||
id String @id @default(cuid())
|
||||
pet Pet @relation(fields: [petId], references: [id], onDelete: Cascade)
|
||||
petId String
|
||||
storageKey String // Supabase Storage object key
|
||||
expiresAt DateTime // set to NOW() + 24 hours on create (D-07)
|
||||
views StoryView[]
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([petId, expiresAt]) // supports lazy-delete filter query
|
||||
}
|
||||
|
||||
model StoryView {
|
||||
story Story @relation(fields: [storyId], references: [id]) // NO onDelete:Cascade (D-08)
|
||||
storyId String
|
||||
viewerPet Pet @relation("StoryViewer", fields: [viewerPetId], references: [id])
|
||||
viewerPetId String
|
||||
viewedAt DateTime @default(now())
|
||||
|
||||
@@id([storyId, viewerPetId]) // deduplication: one view per viewer per story
|
||||
@@index([viewedAt]) // supports 30-day cleanup job (D-08)
|
||||
}
|
||||
|
||||
model Follow {
|
||||
follower Pet @relation("Follower", fields: [followerPetId], references: [id], onDelete: Cascade)
|
||||
followerPetId String
|
||||
followee Pet @relation("Followee", fields: [followeePetId], references: [id], onDelete: Cascade)
|
||||
followeePetId String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@id([followerPetId, followeePetId])
|
||||
@@index([followerPetId])
|
||||
@@index([followeePetId])
|
||||
}
|
||||
|
||||
model Block {
|
||||
blocker Pet @relation("Blocker", fields: [blockerPetId], references: [id], onDelete: Cascade)
|
||||
blockerPetId String
|
||||
blocked Pet @relation("Blocked", fields: [blockedPetId], references: [id], onDelete: Cascade)
|
||||
blockedPetId String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@id([blockerPetId, blockedPetId])
|
||||
@@index([blockerPetId])
|
||||
}
|
||||
|
||||
model Report {
|
||||
id String @id @default(cuid())
|
||||
reporter Pet @relation("Reporter", fields: [reporterPetId], references: [id])
|
||||
reporterPetId String
|
||||
targetPostId String? // null if reporting a profile
|
||||
targetPetId String? // null if reporting a post
|
||||
reason ReportReason
|
||||
notes String? @db.VarChar(500)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@index([reporterPetId])
|
||||
}
|
||||
Reference in new issue
Block a user