init project

This commit is contained in:
root
2026-04-13 13:59:26 -04:00
parent f190e6b91a
commit e26e15f98f
54 changed files with 3280 additions and 0 deletions
@@ -0,0 +1,171 @@
-- CreateEnum
CREATE TYPE "ChatTypeEnum" AS ENUM ('DIRECT', 'GROUP', 'CHANNEL');
-- CreateTable
CREATE TABLE "User" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"passwordHash" TEXT NOT NULL,
"displayName" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Device" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"name" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"lastSeenAt" TIMESTAMP(3),
CONSTRAINT "Device_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "RefreshToken" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"deviceId" TEXT,
"tokenHash" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3) NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "RefreshToken_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Chat" (
"id" TEXT NOT NULL,
"type" "ChatTypeEnum" NOT NULL,
"title" TEXT,
"isBroadcast" BOOLEAN NOT NULL DEFAULT false,
"isPublic" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Chat_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "ChatMember" (
"chatId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"role" TEXT NOT NULL,
"lastReadSeq" INTEGER NOT NULL DEFAULT 0,
"lastDeliveredSeq" INTEGER NOT NULL DEFAULT 0,
CONSTRAINT "ChatMember_pkey" PRIMARY KEY ("chatId","userId")
);
-- CreateTable
CREATE TABLE "Message" (
"id" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
"senderId" TEXT,
"kind" TEXT NOT NULL,
"body" TEXT,
"replyToId" TEXT,
"seq" INTEGER NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"editedAt" TIMESTAMP(3),
"deletedAt" TIMESTAMP(3),
CONSTRAINT "Message_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "MediaObject" (
"id" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"mimeType" TEXT NOT NULL,
"s3Key" TEXT NOT NULL,
"sizeBytes" INTEGER,
"thumbnailKey" TEXT,
"finalized" BOOLEAN NOT NULL DEFAULT false,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "MediaObject_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "MessageMedia" (
"messageId" TEXT NOT NULL,
"mediaId" TEXT NOT NULL,
CONSTRAINT "MessageMedia_pkey" PRIMARY KEY ("messageId","mediaId")
);
-- CreateTable
CREATE TABLE "PinnedMessage" (
"chatId" TEXT NOT NULL,
"messageId" TEXT NOT NULL,
CONSTRAINT "PinnedMessage_pkey" PRIMARY KEY ("chatId","messageId")
);
-- CreateTable
CREATE TABLE "CallSession" (
"id" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
"createdBy" TEXT NOT NULL,
"status" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "CallSession_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Bot" (
"id" TEXT NOT NULL,
"ownerUserId" TEXT NOT NULL,
"displayName" TEXT NOT NULL,
"tokenHash" TEXT NOT NULL,
"webhookUrl" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "Bot_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BotMember" (
"botId" TEXT NOT NULL,
"chatId" TEXT NOT NULL,
CONSTRAINT "BotMember_pkey" PRIMARY KEY ("botId","chatId")
);
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
CREATE UNIQUE INDEX "Message_chatId_seq_key" ON "Message"("chatId", "seq");
CREATE INDEX "Message_chatId_seq_idx" ON "Message"("chatId", "seq");
ALTER TABLE "Device" ADD CONSTRAINT "Device_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "RefreshToken" ADD CONSTRAINT "RefreshToken_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "ChatMember" ADD CONSTRAINT "ChatMember_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "ChatMember" ADD CONSTRAINT "ChatMember_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Message" ADD CONSTRAINT "Message_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Message" ADD CONSTRAINT "Message_senderId_fkey" FOREIGN KEY ("senderId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "MessageMedia" ADD CONSTRAINT "MessageMedia_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "MessageMedia" ADD CONSTRAINT "MessageMedia_mediaId_fkey" FOREIGN KEY ("mediaId") REFERENCES "MediaObject"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "PinnedMessage" ADD CONSTRAINT "PinnedMessage_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "PinnedMessage" ADD CONSTRAINT "PinnedMessage_messageId_fkey" FOREIGN KEY ("messageId") REFERENCES "Message"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "CallSession" ADD CONSTRAINT "CallSession_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "Bot" ADD CONSTRAINT "Bot_ownerUserId_fkey" FOREIGN KEY ("ownerUserId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "BotMember" ADD CONSTRAINT "BotMember_botId_fkey" FOREIGN KEY ("botId") REFERENCES "Bot"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "BotMember" ADD CONSTRAINT "BotMember_chatId_fkey" FOREIGN KEY ("chatId") REFERENCES "Chat"("id") ON DELETE CASCADE ON UPDATE CASCADE;
@@ -0,0 +1 @@
provider = "postgresql"
+152
View File
@@ -0,0 +1,152 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
email String @unique
passwordHash String
displayName String
createdAt DateTime @default(now())
devices Device[]
refreshTokens RefreshToken[]
messages Message[] @relation("MessageSender")
memberships ChatMember[]
bots Bot[]
}
model Device {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
name String?
createdAt DateTime @default(now())
lastSeenAt DateTime?
}
model RefreshToken {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
deviceId String?
tokenHash String
expiresAt DateTime
createdAt DateTime @default(now())
}
enum ChatTypeEnum {
DIRECT
GROUP
CHANNEL
}
model Chat {
id String @id @default(cuid())
type ChatTypeEnum
title String?
isBroadcast Boolean @default(false)
isPublic Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
members ChatMember[]
messages Message[]
pins PinnedMessage[]
calls CallSession[]
botMembers BotMember[]
}
model ChatMember {
chatId String
userId String
role String
lastReadSeq Int @default(0)
lastDeliveredSeq Int @default(0)
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@id([chatId, userId])
}
model Message {
id String @id @default(cuid())
chatId String
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
senderId String?
sender User? @relation("MessageSender", fields: [senderId], references: [id])
kind String
body String?
replyToId String?
seq Int
createdAt DateTime @default(now())
editedAt DateTime?
deletedAt DateTime?
media MessageMedia[]
pins PinnedMessage[]
@@unique([chatId, seq])
@@index([chatId, seq])
}
model MediaObject {
id String @id @default(cuid())
userId String
mimeType String
s3Key String
sizeBytes Int?
thumbnailKey String?
finalized Boolean @default(false)
createdAt DateTime @default(now())
messageLinks MessageMedia[]
}
model MessageMedia {
messageId String
mediaId String
message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)
media MediaObject @relation(fields: [mediaId], references: [id])
@@id([messageId, mediaId])
}
model PinnedMessage {
chatId String
messageId String
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
message Message @relation(fields: [messageId], references: [id], onDelete: Cascade)
@@id([chatId, messageId])
}
model CallSession {
id String @id @default(cuid())
chatId String
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
createdBy String
status String
createdAt DateTime @default(now())
}
model Bot {
id String @id @default(cuid())
ownerUserId String
owner User @relation(fields: [ownerUserId], references: [id], onDelete: Cascade)
displayName String
tokenHash String
webhookUrl String?
createdAt DateTime @default(now())
memberships BotMember[]
}
model BotMember {
botId String
chatId String
bot Bot @relation(fields: [botId], references: [id], onDelete: Cascade)
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
@@id([botId, chatId])
}