rnotes-online/prisma/schema.prisma

202 lines
6.6 KiB
Plaintext

generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// ─── Users ──────────────────────────────────────────────────────────
model User {
id String @id @default(cuid())
did String @unique // EncryptID DID
username String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
notebooks NotebookCollaborator[]
notes Note[]
files File[]
sharedByMe SharedAccess[] @relation("SharedBy")
}
// ─── Notebooks ──────────────────────────────────────────────────────
model Notebook {
id String @id @default(cuid())
title String
slug String @unique
description String? @db.Text
coverColor String @default("#f59e0b")
canvasSlug String?
canvasShapeId String?
isPublic Boolean @default(false)
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
collaborators NotebookCollaborator[]
notes Note[]
sharedAccess SharedAccess[]
@@index([slug])
}
enum CollaboratorRole {
OWNER
EDITOR
VIEWER
}
model NotebookCollaborator {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
notebookId String
notebook Notebook @relation(fields: [notebookId], references: [id], onDelete: Cascade)
role CollaboratorRole @default(VIEWER)
joinedAt DateTime @default(now())
@@unique([userId, notebookId])
@@index([notebookId])
}
// ─── Notes ──────────────────────────────────────────────────────────
model Note {
id String @id @default(cuid())
notebookId String?
notebook Notebook? @relation(fields: [notebookId], references: [id], onDelete: SetNull)
authorId String?
author User? @relation(fields: [authorId], references: [id], onDelete: SetNull)
title String
content String @db.Text
contentPlain String? @db.Text
type NoteType @default(NOTE)
url String?
language String?
mimeType String?
fileUrl String?
fileSize Int?
duration Int?
isPinned Boolean @default(false)
canvasShapeId String?
sortOrder Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// ─── Memory Card fields ─────────────────────────────────────────
parentId String?
parent Note? @relation("NoteTree", fields: [parentId], references: [id], onDelete: SetNull)
children Note[] @relation("NoteTree")
bodyJson Json? // TipTap JSON (canonical format)
bodyMarkdown String? @db.Text // portable markdown for search + Logseq
bodyFormat String @default("html") // "html" | "markdown" | "blocks"
cardType String @default("note") // note|link|file|task|person|idea|reference
summary String? // auto or manual
visibility String @default("private") // private|space|public
position Float? // fractional ordering
properties Json @default("{}") // Logseq-compatible key-value
archivedAt DateTime? // soft-delete
tags NoteTag[]
attachments CardAttachment[]
@@index([notebookId])
@@index([authorId])
@@index([type])
@@index([isPinned])
@@index([parentId])
@@index([cardType])
@@index([archivedAt])
@@index([position])
}
enum NoteType {
NOTE
CLIP
BOOKMARK
CODE
IMAGE
FILE
AUDIO
}
// ─── Files & Attachments ────────────────────────────────────────────
model File {
id String @id @default(cuid())
storageKey String @unique // unique filename on disk
filename String // original filename
mimeType String
sizeBytes Int
checksum String?
authorId String?
author User? @relation(fields: [authorId], references: [id], onDelete: SetNull)
createdAt DateTime @default(now())
attachments CardAttachment[]
}
model CardAttachment {
id String @id @default(cuid())
noteId String
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
fileId String
file File @relation(fields: [fileId], references: [id], onDelete: Cascade)
role String @default("supporting") // "primary"|"preview"|"supporting"
caption String?
position Float @default(0)
createdAt DateTime @default(now())
@@unique([noteId, fileId])
@@index([noteId])
@@index([fileId])
}
// ─── Tags ───────────────────────────────────────────────────────────
model Tag {
id String @id @default(cuid())
name String
color String? @default("#6b7280")
spaceId String @default("") // "" = global, otherwise space-scoped
schema Json?
createdAt DateTime @default(now())
notes NoteTag[]
@@unique([spaceId, name])
@@index([spaceId])
}
model NoteTag {
id String @id @default(cuid())
noteId String
note Note @relation(fields: [noteId], references: [id], onDelete: Cascade)
tagId String
tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)
@@unique([noteId, tagId])
@@index([tagId])
@@index([noteId])
}
// ─── Shared Access ──────────────────────────────────────────────────
model SharedAccess {
id String @id @default(cuid())
notebookId String
notebook Notebook @relation(fields: [notebookId], references: [id], onDelete: Cascade)
sharedById String
sharedBy User @relation("SharedBy", fields: [sharedById], references: [id], onDelete: Cascade)
targetDid String
role CollaboratorRole @default(VIEWER)
createdAt DateTime @default(now())
@@unique([notebookId, targetDid])
@@index([targetDid])
}