forked from dubinc/dub
-
Notifications
You must be signed in to change notification settings - Fork 0
/
schema.prisma
230 lines (192 loc) · 7.01 KB
/
schema.prisma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextSearch", "fullTextIndex"]
}
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
accounts Account[]
sessions Session[]
projects ProjectUsers[]
links Link[]
createdAt DateTime @default(now())
}
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@index([userId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
model Project {
id String @id @default(cuid())
name String
slug String @unique
logo String?
users ProjectUsers[]
invites ProjectInvite[]
usage Int @default(0)
usageLimit Int @default(1000)
plan String @default("free")
stripeId String? @unique // Stripe subscription ID
billingCycleStart Int? // day of the month when the billing cycle starts
sentEmails SentEmail[]
domains Domain[]
links Link[]
tags Tag[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ProjectInvite {
email String
expires DateTime
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
createdAt DateTime @default(now())
@@unique([email, projectId])
@@index([projectId])
}
enum Role {
owner
member
}
model ProjectUsers {
id String @id @default(cuid())
role Role @default(member)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String
@@unique([userId, projectId])
@@index([projectId])
}
enum EmailType {
firstDomainInvalidEmail
secondDomainInvalidEmail
firstUsageLimitEmail
secondUsageLimitEmail
}
model SentEmail {
id String @id @default(cuid())
type EmailType
createdAt DateTime @default(now())
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String?
@@index([projectId])
}
model Domain {
id String @id @default(cuid())
slug String @unique
verified Boolean @default(false)
target String?
type String @default("redirect")
description String?
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
projectId String?
primary Boolean @default(false)
links Link[]
lastChecked DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index(projectId)
@@index(lastChecked)
}
model Link {
id String @id @default(cuid())
domain String // domain of the link (e.g. dub.sh) – also stored on Redis
key String // key of the link (e.g. /github) – also stored on Redis
url String @db.LongText // target url (e.g. https://github.com/steven-tey/dub) – also stored on Redis
archived Boolean @default(false) // whether the link is archived or not
expiresAt DateTime? // when the link expires – stored on Redis via ttl
password String? // password to access the link – also stored on Redis
proxy Boolean @default(false) // Proxy to use custom OG tags (stored on redis) – if false, will use OG tags from target url
title String? // OG title for the link (e.g. Dub - Open-Source Bitly Alternative)
description String? @db.VarChar(280) // OG description for the link (e.g. An open-source link management tool for modern marketing teams to create, share, and track short links.)
image String? @db.LongText // OG image for the link (e.g. https://dub.sh/og-image.png)
// UTM parameters
utm_source String? // UTM source for the link (e.g. youtube.com)
utm_medium String? // UTM medium for the link (e.g. social)
utm_campaign String? // UTM campaign for the link (e.g. summer-sale)
utm_term String? // UTM term for the link (e.g. dub)
utm_content String? // UTM content for the link (e.g. description)
// Link cloaking/masking via rewrite
rewrite Boolean @default(false) // whether to rewrite the link or not
// Custom device targeting
ios String? @db.LongText // custom link for iOS devices
android String? @db.LongText // custom link for Android devices
// User who created the link
user User? @relation(fields: [userId], references: [id])
userId String?
// Project that the link belongs to
project Project? @relation(fields: [projectId], references: [id], onUpdate: Cascade, onDelete: Cascade)
projectId String?
// Relational reference to the project domain
projectDomain Domain? @relation(fields: [domain], references: [slug], onUpdate: Cascade, onDelete: Cascade)
// Link metadata
clicks Int @default(0) // number of clicks
publicStats Boolean @default(false) // whether to show public stats or not
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Link tags
tag Tag? @relation(fields: [tagId], references: [id])
tagId String?
// TODO: might wanna add indices for utm_source, utm_medium, utm_campaign
@@unique([domain, key])
@@index(projectId)
@@index(domain)
@@index(tagId)
@@index(proxy)
@@index(password)
@@index(createdAt(sort: Desc))
@@index(clicks(sort: Desc))
@@index(userId)
@@fulltext([key, url])
}
model Tag {
id String @id @default(cuid())
name String
color String @default("blue")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
project Project @relation(fields: [projectId], references: [id], onUpdate: Cascade, onDelete: Cascade)
projectId String
links Link[]
@@unique([name, projectId])
@@index(projectId)
}