|
1 | 1 | import { relations, sql } from 'drizzle-orm'; |
2 | 2 | import { |
3 | 3 | pgTable, |
| 4 | + varchar, |
4 | 5 | text, |
| 6 | + boolean, |
| 7 | + integer, |
| 8 | + timestamp, |
| 9 | + index, |
| 10 | + uniqueIndex, |
| 11 | + check, |
5 | 12 | } from 'drizzle-orm/pg-core'; |
6 | 13 | import { user } from './user'; |
7 | 14 | import { section } from './section'; |
8 | 15 |
|
9 | | -export const file = pgTable('file', { |
10 | | - id: text('id') |
11 | | - .default(sql`nanoid(20)`) |
12 | | - .primaryKey(), |
13 | | - authorId: text('author_id') |
14 | | - .notNull() |
15 | | - .references(() => user.id), |
16 | | - sectionId: text('section_id').references(() => section.id), |
17 | | - file_name: text('file_name').notNull(), |
18 | | -}); |
| 16 | +export const file = pgTable( |
| 17 | + 'file', |
| 18 | + { |
| 19 | + // NOTE: Use for storing in the bucket, not file name or file title. |
| 20 | + id: varchar('id', { length: 20 }) |
| 21 | + .default(sql`nanoid(20)`) |
| 22 | + .primaryKey(), |
| 23 | + |
| 24 | + authorId: text('author_id') |
| 25 | + .notNull() |
| 26 | + .references(() => user.id, { onDelete: 'cascade' }), // Could be 'set null' too, depending on what we want to do with it. |
| 27 | + |
| 28 | + sectionId: varchar('section_id', { length: 6 }) |
| 29 | + .references(() => section.id, { onDelete: 'set null' }), |
| 30 | + |
| 31 | + fileTitle: text('file_title') |
| 32 | + .notNull(), |
| 33 | + |
| 34 | + fileName: text('file_name') |
| 35 | + .notNull(), |
| 36 | + |
| 37 | + publishDate: timestamp('publish_date', { withTimezone: true }) |
| 38 | + .notNull() |
| 39 | + .defaultNow(), |
| 40 | + |
| 41 | + likes: integer('likes') |
| 42 | + .notNull() |
| 43 | + .default(0), |
| 44 | + saves: integer('saves') |
| 45 | + .notNull() |
| 46 | + .default(0), |
| 47 | + |
| 48 | + // Edit flag for future workflows |
| 49 | + edited: boolean('edited').notNull().default(false), |
| 50 | + |
| 51 | + createdAt: timestamp('created_at', { withTimezone: true }) |
| 52 | + .notNull() |
| 53 | + .defaultNow(), |
| 54 | + editedAt: timestamp('edited_at', { withTimezone: true }) |
| 55 | + .notNull() |
| 56 | + .defaultNow(), |
| 57 | + }, |
| 58 | + (t) => ([ |
| 59 | + // REVIEW: This is CASE SENSITIVE. File != file similar to Linux. |
| 60 | + // So a user could have "Lecture 1 Notes" and "lecture 1 notes". |
| 61 | + // I would recommend adding a PG extension for to support insensitivity. |
| 62 | + uniqueIndex('file_title_unique_idx').on(t.authorId, t.fileTitle), |
| 63 | + index('file_by_author_idx').on(t.authorId), |
| 64 | + index('file_by_section_idx').on(t.sectionId), |
| 65 | + index('file_by_publish_date_idx').on(t.publishDate), |
| 66 | + |
| 67 | + check('file_likes_nonneg', sql`${t.likes} >= 0`), |
| 68 | + check('file_saves_nonneg', sql`${t.saves} >= 0`), |
| 69 | + ]), |
| 70 | +); |
19 | 71 |
|
20 | 72 | export const fileRelations = relations(file, ({ one }) => ({ |
21 | 73 | author: one(user, { |
|
0 commit comments