Initial Commit

This commit is contained in:
Dries Augustyns
2024-07-23 13:49:48 +02:00
commit 91a8840c3c
191 changed files with 36022 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
@@ -0,0 +1,330 @@
-- CreateEnum
CREATE TYPE "TemplateType" AS ENUM ('MARKETING', 'TRANSACTIONAL');
-- CreateEnum
CREATE TYPE "TemplateStyle" AS ENUM ('PLUNK', 'HTML');
-- CreateEnum
CREATE TYPE "EmailStatus" AS ENUM ('SENT', 'DELIVERED', 'BOUNCED', 'OPENED', 'COMPLAINT');
-- CreateEnum
CREATE TYPE "CampaignStatus" AS ENUM ('DRAFT', 'SCHEDULED', 'DELIVERED');
-- CreateEnum
CREATE TYPE "Role" AS ENUM ('OWNER', 'ADMIN', 'MEMBER');
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"password" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "projects" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"url" TEXT NOT NULL,
"verified" BOOLEAN NOT NULL DEFAULT false,
"email" TEXT,
"from" TEXT,
"public" TEXT NOT NULL,
"secret" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "projects_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "projectmemberhips" (
"role" "Role" NOT NULL DEFAULT 'MEMBER',
"userId" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "projectmemberhips_pkey" PRIMARY KEY ("userId","projectId")
);
-- CreateTable
CREATE TABLE "events" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"projectId" TEXT NOT NULL,
"templateId" TEXT,
"campaignId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "events_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "templates" (
"id" TEXT NOT NULL,
"subject" TEXT NOT NULL,
"body" TEXT NOT NULL,
"type" "TemplateType" NOT NULL,
"style" "TemplateStyle" NOT NULL,
"projectId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "templates_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "actions" (
"id" TEXT NOT NULL,
"name" TEXT NOT NULL,
"runOnce" BOOLEAN NOT NULL DEFAULT false,
"delay" INTEGER NOT NULL DEFAULT 0,
"projectId" TEXT NOT NULL,
"templateId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "actions_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "campaigns" (
"id" TEXT NOT NULL,
"subject" TEXT NOT NULL,
"body" TEXT NOT NULL,
"status" "CampaignStatus" NOT NULL DEFAULT 'DRAFT',
"delivered" TIMESTAMP(3),
"style" "TemplateStyle" NOT NULL,
"projectId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "campaigns_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "triggers" (
"id" TEXT NOT NULL,
"contactId" TEXT NOT NULL,
"eventId" TEXT,
"actionId" TEXT,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "triggers_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "contacts" (
"id" TEXT NOT NULL,
"email" TEXT NOT NULL,
"subscribed" BOOLEAN NOT NULL DEFAULT true,
"data" TEXT,
"projectId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "contacts_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "emails" (
"id" TEXT NOT NULL,
"messageId" TEXT NOT NULL,
"subject" TEXT,
"body" TEXT,
"status" "EmailStatus" NOT NULL DEFAULT 'SENT',
"projectId" TEXT,
"actionId" TEXT,
"campaignId" TEXT,
"contactId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "emails_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "clicks" (
"id" TEXT NOT NULL,
"link" TEXT NOT NULL,
"emailId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "clicks_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "tasks" (
"id" TEXT NOT NULL,
"runBy" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"actionId" TEXT,
"campaignId" TEXT,
"contactId" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "tasks_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "_ActionToEvent" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "_ActionToNotEvent" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL
);
-- CreateTable
CREATE TABLE "_CampaignToContact" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
-- CreateIndex
CREATE UNIQUE INDEX "projects_public_key" ON "projects"("public");
-- CreateIndex
CREATE UNIQUE INDEX "projects_secret_key" ON "projects"("secret");
-- CreateIndex
CREATE INDEX "events_projectId_templateId_campaignId_idx" ON "events"("projectId", "templateId", "campaignId");
-- CreateIndex
CREATE INDEX "templates_projectId_idx" ON "templates"("projectId");
-- CreateIndex
CREATE INDEX "actions_projectId_templateId_idx" ON "actions"("projectId", "templateId");
-- CreateIndex
CREATE INDEX "campaigns_projectId_idx" ON "campaigns"("projectId");
-- CreateIndex
CREATE INDEX "triggers_contactId_eventId_actionId_createdAt_idx" ON "triggers"("contactId", "eventId", "actionId", "createdAt");
-- CreateIndex
CREATE INDEX "contacts_projectId_idx" ON "contacts"("projectId");
-- CreateIndex
CREATE UNIQUE INDEX "emails_messageId_key" ON "emails"("messageId");
-- CreateIndex
CREATE INDEX "emails_projectId_actionId_campaignId_contactId_createdAt_idx" ON "emails"("projectId", "actionId", "campaignId", "contactId", "createdAt");
-- CreateIndex
CREATE INDEX "clicks_emailId_createdAt_idx" ON "clicks"("emailId", "createdAt");
-- CreateIndex
CREATE INDEX "tasks_runBy_createdAt_idx" ON "tasks"("runBy", "createdAt");
-- CreateIndex
CREATE UNIQUE INDEX "_ActionToEvent_AB_unique" ON "_ActionToEvent"("A", "B");
-- CreateIndex
CREATE INDEX "_ActionToEvent_B_index" ON "_ActionToEvent"("B");
-- CreateIndex
CREATE UNIQUE INDEX "_ActionToNotEvent_AB_unique" ON "_ActionToNotEvent"("A", "B");
-- CreateIndex
CREATE INDEX "_ActionToNotEvent_B_index" ON "_ActionToNotEvent"("B");
-- CreateIndex
CREATE UNIQUE INDEX "_CampaignToContact_AB_unique" ON "_CampaignToContact"("A", "B");
-- CreateIndex
CREATE INDEX "_CampaignToContact_B_index" ON "_CampaignToContact"("B");
-- AddForeignKey
ALTER TABLE "projectmemberhips" ADD CONSTRAINT "projectmemberhips_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "projectmemberhips" ADD CONSTRAINT "projectmemberhips_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "events" ADD CONSTRAINT "events_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "events" ADD CONSTRAINT "events_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "templates"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "events" ADD CONSTRAINT "events_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "templates" ADD CONSTRAINT "templates_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "actions" ADD CONSTRAINT "actions_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "actions" ADD CONSTRAINT "actions_templateId_fkey" FOREIGN KEY ("templateId") REFERENCES "templates"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "campaigns" ADD CONSTRAINT "campaigns_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "triggers" ADD CONSTRAINT "triggers_contactId_fkey" FOREIGN KEY ("contactId") REFERENCES "contacts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "triggers" ADD CONSTRAINT "triggers_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "triggers" ADD CONSTRAINT "triggers_actionId_fkey" FOREIGN KEY ("actionId") REFERENCES "actions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "contacts" ADD CONSTRAINT "contacts_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "emails" ADD CONSTRAINT "emails_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "projects"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "emails" ADD CONSTRAINT "emails_actionId_fkey" FOREIGN KEY ("actionId") REFERENCES "actions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "emails" ADD CONSTRAINT "emails_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "emails" ADD CONSTRAINT "emails_contactId_fkey" FOREIGN KEY ("contactId") REFERENCES "contacts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "clicks" ADD CONSTRAINT "clicks_emailId_fkey" FOREIGN KEY ("emailId") REFERENCES "emails"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "tasks" ADD CONSTRAINT "tasks_actionId_fkey" FOREIGN KEY ("actionId") REFERENCES "actions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "tasks" ADD CONSTRAINT "tasks_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "tasks" ADD CONSTRAINT "tasks_contactId_fkey" FOREIGN KEY ("contactId") REFERENCES "contacts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ActionToEvent" ADD CONSTRAINT "_ActionToEvent_A_fkey" FOREIGN KEY ("A") REFERENCES "actions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ActionToEvent" ADD CONSTRAINT "_ActionToEvent_B_fkey" FOREIGN KEY ("B") REFERENCES "events"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ActionToNotEvent" ADD CONSTRAINT "_ActionToNotEvent_A_fkey" FOREIGN KEY ("A") REFERENCES "actions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_ActionToNotEvent" ADD CONSTRAINT "_ActionToNotEvent_B_fkey" FOREIGN KEY ("B") REFERENCES "events"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_CampaignToContact" ADD CONSTRAINT "_CampaignToContact_A_fkey" FOREIGN KEY ("A") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_CampaignToContact" ADD CONSTRAINT "_CampaignToContact_B_fkey" FOREIGN KEY ("B") REFERENCES "contacts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+3
View File
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
+329
View File
@@ -0,0 +1,329 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
// Credentials
email String @unique
password String?
// Relations
memberships ProjectMembership[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users")
}
model Project {
id String @id @default(uuid())
// Details
name String
url String
// Verified domain
verified Boolean @default(false)
email String?
from String?
// API access
public String @unique
secret String @unique
// Relations
memberships ProjectMembership[]
contacts Contact[]
campaigns Campaign[]
actions Action[]
events Event[]
templates Template[]
emails Email[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("projects")
}
// Table to maintain many-to-many relationship between Account and Project
model ProjectMembership {
role Role @default(MEMBER)
// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@id(fields: [userId, projectId])
@@map("projectmemberhips")
}
model Event {
id String @id @default(uuid())
// Details
name String
// Relations
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
template Template? @relation(fields: [templateId], references: [id], onDelete: Cascade)
templateId String?
campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: Cascade)
campaignId String?
actions Action[] @relation("ActionToEvent")
notActions Action[] @relation("ActionToNotEvent")
triggers Trigger[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId, templateId, campaignId])
@@map("events")
}
model Template {
id String @id @default(uuid())
// Details
subject String
body String
type TemplateType
style TemplateStyle
// Relations
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
events Event[]
actions Action[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId])
@@map("templates")
}
model Action {
id String @id @default(uuid())
// Details
name String
runOnce Boolean @default(false)
delay Int @default(0)
// Relations
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
template Template @relation(fields: [templateId], references: [id])
templateId String
events Event[] @relation("ActionToEvent")
notevents Event[] @relation("ActionToNotEvent")
triggers Trigger[]
emails Email[]
tasks Task[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId, templateId])
@@map("actions")
}
model Campaign {
id String @id @default(uuid())
subject String
body String
status CampaignStatus @default(DRAFT)
delivered DateTime?
style TemplateStyle
// Relations
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
emails Email[]
tasks Task[]
recipients Contact[]
events Event[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId])
@@map("campaigns")
}
model Trigger {
id String @id @default(uuid())
// Relations
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
contactId String
event Event? @relation(fields: [eventId], references: [id], onDelete: Cascade)
eventId String?
action Action? @relation(fields: [actionId], references: [id], onDelete: Cascade)
actionId String?
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [contactId, eventId, actionId, createdAt])
@@map("triggers")
}
model Contact {
id String @id @default(uuid())
// Details
email String
subscribed Boolean @default(true)
data String?
// Relations
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
emails Email[]
triggers Trigger[]
tasks Task[]
campaigns Campaign[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId])
@@map("contacts")
}
model Email {
id String @id @default(uuid())
messageId String @unique
subject String?
body String?
status EmailStatus @default(SENT)
// Relations
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String?
action Action? @relation(fields: [actionId], references: [id], onDelete: Cascade)
actionId String?
campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: Cascade)
campaignId String?
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
contactId String
clicks Click[]
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(fields: [projectId, actionId, campaignId, contactId, createdAt])
@@map("emails")
}
model Click {
id String @id @default(uuid())
link String
// Relations
email Email @relation(fields: [emailId], references: [id], onDelete: Cascade)
emailId String
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([emailId, createdAt])
@@map("clicks")
}
model Task {
id String @id @default(uuid())
// Details
runBy DateTime @default(now())
// Relations
action Action? @relation(fields: [actionId], references: [id], onDelete: Cascade)
actionId String?
campaign Campaign? @relation(fields: [campaignId], references: [id], onDelete: Cascade)
campaignId String?
contact Contact @relation(fields: [contactId], references: [id], onDelete: Cascade)
contactId String
// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([runBy, createdAt])
@@map("tasks")
}
enum TemplateType {
MARKETING
TRANSACTIONAL
}
enum TemplateStyle {
PLUNK
HTML
}
enum EmailStatus {
SENT
DELIVERED
BOUNCED
OPENED
COMPLAINT
}
enum CampaignStatus {
DRAFT
SCHEDULED
DELIVERED
}
enum Role {
OWNER
ADMIN
MEMBER
}