-
Notifications
You must be signed in to change notification settings - Fork 2
/
schema.prisma
169 lines (141 loc) · 5.34 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
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
previewFeatures = ["postgresqlExtensions"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
extensions = [citext]
}
model Recipe {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
author User @relation(fields: [authorId], references: [id])
authorId String @db.Uuid
name String @db.Citext
slug String @db.Citext
servings Int?
sources RecipeSource[]
ingredients RecipeIngredient[]
categories Category[]
steps String[]
notes RecipeNote[]
cookingHistory CookingHistory[]
@@unique([authorId, name])
@@unique([authorId, slug])
}
/// Where a recipe came from. Unless someone invented the recipe by themself,
/// it's polite to attribute a source.
model RecipeSource {
id Int @id @default(autoincrement())
Recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
recipeId Int
type SourceType
name String?
url String?
@@index([recipeId, type])
}
enum SourceType {
/// Directly copied from someone else's recipe.
BY_PERSON
/// Directly copied from a recipe on a webpage.
FROM_WEBPAGE
/// Modified from someone else's recipe.
BASED_ON_PERSON
/// Modified from a recipe on a webpage.
BASED_ON_WEBPAGE
}
/// An ingredient line in a recipe, like "1 cup sugar".
model RecipeIngredient {
/// Gives the ingredients an order in the recipe.
order Int
amount String?
/// A missing unit means the ingredient comes in items, like "3 eggs".
unit String?
name String
/// How the ingredient was prepared, like "chopped".
preparation String?
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
recipeId Int
@@id([recipeId, order])
}
// Anyone can add a note to any recipe. These notes hold both free-form comments and information on
// when someone cooked the recipe. Empty comments won't be shown on the default recipe view, but
// they can contribute to an average cooking time or help someone find a recipe based on when they
// cooked it.
model RecipeNote {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
recipeId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId String @db.Uuid
// Markdown-formatted. Not shown if it's empty.
content String @default("")
// True if the author wants to show this note to other people.
public Boolean @default(true)
// True if the recipe's author doesn't want the note to appear on their recipe.
hidden Boolean @default(false)
}
model CookingHistory {
id Int @id @default(autoincrement())
recipe Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
recipeId Int
cook User @relation(fields: [cookId], references: [id], onDelete: Cascade)
cookId String @db.Uuid
// The local time the recipe was cooked, because this is for a user's personal history and doesn't
// need to be consistent across users. Once https://github.com/prisma/prisma/issues/20615 is
// fixed, I can replace this with a PlainDate field.
cookedAtYear Int @db.SmallInt
cookedAtMonth Int @db.SmallInt
cookedAtDay Int? @db.SmallInt
@@unique([recipeId, cookId, cookedAtYear, cookedAtMonth, cookedAtDay])
@@index([cookId, cookedAtYear, cookedAtMonth])
}
model Category {
id Int @id @default(autoincrement())
name String @unique @db.Citext
Recipes Recipe[]
}
// Recipes that are partway through being imported but might not fully fit the
// database's data model. These will be manageable through the /account page.
model DraftRecipe {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @db.Timestamptz(3)
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @db.Uuid
// Expected to conform to @lib/json-recipe.ts/JsonRecipe.
data Json
@@index(userId)
}
model User {
id String @id @default(uuid()) @db.Uuid
name String
username String @unique @db.Citext
Recipes Recipe[]
DraftRecipes DraftRecipe[]
GoogleUser GoogleUser[]
sessions Session[]
recipeNotes RecipeNote[]
CookingHistory CookingHistory[]
}
model GoogleUser {
/// Google's ID, exposed as the 'sub' claim in their JWTs.
gid String @id
/// The user's verified email address, which this app uses to create inter-user trust
/// relationships.
email String @unique
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @db.Uuid
}
model Session {
// 128-bit random ID, base64url-encoded, for storing in a client-side cookie.
id String @id
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @db.Uuid
expires DateTime @db.Timestamptz(3)
}