kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { relations } from "drizzle-orm";
2import {
3 boolean,
4 index,
5 integer,
6 pgTable,
7 text,
8 timestamp,
9 uniqueIndex,
10} from "drizzle-orm/pg-core";
11
12export const user = pgTable("user", {
13 id: text("id").primaryKey(),
14 name: text("name").notNull(),
15 email: text("email").notNull().unique(),
16 emailVerified: boolean("email_verified").default(false).notNull(),
17 image: text("image"),
18 locale: text("locale"),
19 createdAt: timestamp("created_at").defaultNow().notNull(),
20 updatedAt: timestamp("updated_at")
21 .defaultNow()
22 .$onUpdate(() => /* @__PURE__ */ new Date())
23 .notNull(),
24 isAnonymous: boolean("is_anonymous").default(false),
25});
26
27export const session = pgTable(
28 "session",
29 {
30 id: text("id").primaryKey(),
31 expiresAt: timestamp("expires_at").notNull(),
32 token: text("token").notNull().unique(),
33 createdAt: timestamp("created_at").defaultNow().notNull(),
34 updatedAt: timestamp("updated_at")
35 .$onUpdate(() => /* @__PURE__ */ new Date())
36 .notNull(),
37 ipAddress: text("ip_address"),
38 userAgent: text("user_agent"),
39 userId: text("user_id")
40 .notNull()
41 .references(() => user.id, { onDelete: "cascade" }),
42 activeOrganizationId: text("active_organization_id"),
43 activeTeamId: text("active_team_id"),
44 },
45 (table) => [index("session_userId_idx").on(table.userId)],
46);
47
48export const account = pgTable(
49 "account",
50 {
51 id: text("id").primaryKey(),
52 accountId: text("account_id").notNull(),
53 providerId: text("provider_id").notNull(),
54 userId: text("user_id")
55 .notNull()
56 .references(() => user.id, { onDelete: "cascade" }),
57 accessToken: text("access_token"),
58 refreshToken: text("refresh_token"),
59 idToken: text("id_token"),
60 accessTokenExpiresAt: timestamp("access_token_expires_at"),
61 refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
62 scope: text("scope"),
63 password: text("password"),
64 createdAt: timestamp("created_at").defaultNow().notNull(),
65 updatedAt: timestamp("updated_at")
66 .$onUpdate(() => /* @__PURE__ */ new Date())
67 .notNull(),
68 },
69 (table) => [index("account_userId_idx").on(table.userId)],
70);
71
72export const verification = pgTable(
73 "verification",
74 {
75 id: text("id").primaryKey(),
76 identifier: text("identifier").notNull(),
77 value: text("value").notNull(),
78 expiresAt: timestamp("expires_at").notNull(),
79 createdAt: timestamp("created_at").defaultNow().notNull(),
80 updatedAt: timestamp("updated_at")
81 .defaultNow()
82 .$onUpdate(() => /* @__PURE__ */ new Date())
83 .notNull(),
84 },
85 (table) => [index("verification_identifier_idx").on(table.identifier)],
86);
87
88export const workspace = pgTable(
89 "workspace",
90 {
91 id: text("id").primaryKey(),
92 name: text("name").notNull(),
93 slug: text("slug").notNull().unique(),
94 logo: text("logo"),
95 createdAt: timestamp("created_at").notNull(),
96 metadata: text("metadata"),
97 description: text("description"),
98 },
99 (table) => [uniqueIndex("workspace_slug_uidx").on(table.slug)],
100);
101
102export const team = pgTable(
103 "team",
104 {
105 id: text("id").primaryKey(),
106 name: text("name").notNull(),
107 workspaceId: text("workspace_id")
108 .notNull()
109 .references(() => workspace.id, { onDelete: "cascade" }),
110 createdAt: timestamp("created_at").notNull(),
111 updatedAt: timestamp("updated_at").$onUpdate(
112 () => /* @__PURE__ */ new Date(),
113 ),
114 },
115 (table) => [index("team_workspaceId_idx").on(table.workspaceId)],
116);
117
118export const teamMember = pgTable(
119 "team_member",
120 {
121 id: text("id").primaryKey(),
122 teamId: text("team_id")
123 .notNull()
124 .references(() => team.id, { onDelete: "cascade" }),
125 userId: text("user_id")
126 .notNull()
127 .references(() => user.id, { onDelete: "cascade" }),
128 createdAt: timestamp("created_at"),
129 },
130 (table) => [
131 index("teamMember_teamId_idx").on(table.teamId),
132 index("teamMember_userId_idx").on(table.userId),
133 ],
134);
135
136export const workspace_member = pgTable(
137 "workspace_member",
138 {
139 id: text("id").primaryKey(),
140 workspaceId: text("workspace_id")
141 .notNull()
142 .references(() => workspace.id, { onDelete: "cascade" }),
143 userId: text("user_id")
144 .notNull()
145 .references(() => user.id, { onDelete: "cascade" }),
146 role: text("role").default("member").notNull(),
147 joinedAt: timestamp("joined_at").notNull(),
148 },
149 (table) => [
150 index("workspace_member_workspaceId_idx").on(table.workspaceId),
151 index("workspace_member_userId_idx").on(table.userId),
152 ],
153);
154
155export const invitation = pgTable(
156 "invitation",
157 {
158 id: text("id").primaryKey(),
159 workspaceId: text("workspace_id")
160 .notNull()
161 .references(() => workspace.id, { onDelete: "cascade" }),
162 email: text("email").notNull(),
163 role: text("role"),
164 teamId: text("team_id"),
165 status: text("status").default("pending").notNull(),
166 expiresAt: timestamp("expires_at").notNull(),
167 createdAt: timestamp("created_at").defaultNow().notNull(),
168 inviterId: text("inviter_id")
169 .notNull()
170 .references(() => user.id, { onDelete: "cascade" }),
171 },
172 (table) => [
173 index("invitation_workspaceId_idx").on(table.workspaceId),
174 index("invitation_email_idx").on(table.email),
175 ],
176);
177
178export const apikey = pgTable(
179 "apikey",
180 {
181 id: text("id").primaryKey(),
182 configId: text("config_id").default("default").notNull(),
183 name: text("name"),
184 start: text("start"),
185 referenceId: text("reference_id").notNull(),
186 prefix: text("prefix"),
187 key: text("key").notNull(),
188 refillInterval: integer("refill_interval"),
189 refillAmount: integer("refill_amount"),
190 lastRefillAt: timestamp("last_refill_at"),
191 enabled: boolean("enabled").default(true),
192 rateLimitEnabled: boolean("rate_limit_enabled").default(true),
193 rateLimitTimeWindow: integer("rate_limit_time_window").default(86400000),
194 rateLimitMax: integer("rate_limit_max").default(10),
195 requestCount: integer("request_count").default(0),
196 remaining: integer("remaining"),
197 lastRequest: timestamp("last_request"),
198 expiresAt: timestamp("expires_at"),
199 createdAt: timestamp("created_at").notNull(),
200 updatedAt: timestamp("updated_at").notNull(),
201 permissions: text("permissions"),
202 metadata: text("metadata"),
203 },
204 (table) => [
205 index("apikey_configId_idx").on(table.configId),
206 index("apikey_referenceId_idx").on(table.referenceId),
207 index("apikey_key_idx").on(table.key),
208 ],
209);
210
211export const userRelations = relations(user, ({ many }) => ({
212 sessions: many(session),
213 accounts: many(account),
214 teamMembers: many(teamMember),
215 workspace_members: many(workspace_member),
216 invitations: many(invitation),
217}));
218
219export const sessionRelations = relations(session, ({ one }) => ({
220 user: one(user, {
221 fields: [session.userId],
222 references: [user.id],
223 }),
224}));
225
226export const accountRelations = relations(account, ({ one }) => ({
227 user: one(user, {
228 fields: [account.userId],
229 references: [user.id],
230 }),
231}));
232
233export const workspaceRelations = relations(workspace, ({ many }) => ({
234 teams: many(team),
235 workspace_members: many(workspace_member),
236 invitations: many(invitation),
237}));
238
239export const teamRelations = relations(team, ({ one, many }) => ({
240 workspace: one(workspace, {
241 fields: [team.workspaceId],
242 references: [workspace.id],
243 }),
244 teamMembers: many(teamMember),
245}));
246
247export const teamMemberRelations = relations(teamMember, ({ one }) => ({
248 team: one(team, {
249 fields: [teamMember.teamId],
250 references: [team.id],
251 }),
252 user: one(user, {
253 fields: [teamMember.userId],
254 references: [user.id],
255 }),
256}));
257
258export const workspace_memberRelations = relations(
259 workspace_member,
260 ({ one }) => ({
261 workspace: one(workspace, {
262 fields: [workspace_member.workspaceId],
263 references: [workspace.id],
264 }),
265 user: one(user, {
266 fields: [workspace_member.userId],
267 references: [user.id],
268 }),
269 }),
270);
271
272export const invitationRelations = relations(invitation, ({ one }) => ({
273 workspace: one(workspace, {
274 fields: [invitation.workspaceId],
275 references: [workspace.id],
276 }),
277 user: one(user, {
278 fields: [invitation.inviterId],
279 references: [user.id],
280 }),
281}));