-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(portal): create initial portal database schemas #134
base: main
Are you sure you want to change the base?
Changes from all commits
da7c65a
1f69464
cbf3f49
e832ad2
479b8a2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { boolean, pgEnum, pgTable, serial, varchar } from 'drizzle-orm/pg-core' | ||
|
||
export const relationshipEnum = pgEnum('relationship', ['mother', 'father', 'sibling', 'friend', 'relative', 'other']) | ||
|
||
export const emergencyContact = pgTable('emergencyContact', { | ||
id: serial('id').primaryKey(), | ||
name: varchar('name', { length: 32 }), | ||
relationship: relationshipEnum('relationship'), | ||
phoneNumber: varchar('phoneNumber', { length: 16 }).unique(), | ||
isPhoneNumberVerified: boolean('isPhoneNumberVerified').default(false), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,9 @@ | ||
export * from './user' | ||
export * from './emergencyContact' | ||
export * from './program' | ||
export * from './resume' | ||
export * from './school' | ||
export * from './session' | ||
export * from './socialMedia' | ||
export * from './team' | ||
export * from './user' | ||
export * from './userPreferences' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { integer, pgEnum, pgTable, serial, varchar } from 'drizzle-orm/pg-core' | ||
import { school } from './school' | ||
|
||
export const programTypeEnum = pgEnum('programType', ['bachelor', 'master', 'diploma', 'certificate']) | ||
|
||
export const program = pgTable('program', { | ||
id: serial('id').primaryKey(), | ||
name: varchar('name', { length: 128 }), | ||
schoolId: integer('schoolId').references(() => school.id), | ||
programType: programTypeEnum('programType'), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { boolean, pgTable, serial, timestamp, varchar } from 'drizzle-orm/pg-core' | ||
|
||
export const resume = pgTable('resume', { | ||
id: serial('id').primaryKey(), | ||
fileLink: varchar('fileLink', { length: 128 }), | ||
hasPrivacyToggle: boolean('hasPrivacyToggle').default(false), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good touch π |
||
uploadedAt: timestamp('uploadedAt').defaultNow(), | ||
}) | ||
Comment on lines
+3
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider enhancing the resume table structure. The current schema is a good start, but consider the following improvements:
userId: integer('userId').notNull().references(() => users.id),
fileLink: varchar('fileLink', { length: 128 }).notNull(),
{ name: 'fileLink_idx', columns: [resume.fileLink] }
name: varchar('name', { length: 255 }).notNull(), These changes would enhance data integrity and query performance. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { pgEnum, pgTable, serial, varchar } from 'drizzle-orm/pg-core' | ||
|
||
export const levelOfStudyEnum = pgEnum('levelOfStudy', ['graduateSchool', 'highSchool']) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider expanding the levelOfStudyEnum. The current enum covers graduate and high school levels, which might not be comprehensive enough for all potential use cases. Consider including additional levels such as 'undergraduate', 'middleSchool', or 'elementary' to make the schema more flexible for future requirements. Here's a suggested expansion of the enum: export const levelOfStudyEnum = pgEnum('levelOfStudy', [
'elementary',
'middleSchool',
'highSchool',
'undergraduate',
'graduateSchool'
]) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need for highschool right now, should be added on later imo |
||
|
||
export const school = pgTable('school', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea to add a location to this as well |
||
id: serial('id').primaryKey(), | ||
name: varchar('name', { length: 128 }), | ||
levelOfStudy: levelOfStudyEnum('levelOfStudy'), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,10 @@ import { user } from './user' | |
|
||
export const session = pgTable('session', { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we good to make this table before finalizing the auth provider? |
||
id: text('id').primaryKey(), | ||
userId: text('user_id') | ||
userId: text('userId') | ||
.notNull() | ||
.references(() => user.id), | ||
expiresAt: timestamp('expires_at', { | ||
expiresAt: timestamp('expiresAt', { | ||
withTimezone: true, | ||
mode: 'date', | ||
}).notNull(), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { integer, pgTable, serial, varchar } from 'drizzle-orm/pg-core' | ||
|
||
import { user } from './user' | ||
|
||
export const socialMedia = pgTable('socialMedia', { | ||
id: serial('id').primaryKey(), | ||
userId: integer('userId') | ||
.references(() => user.id), | ||
platformName: varchar('platformName', { length: 16 }), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should reference another |
||
profileUrl: varchar('profileUrl', { length: 128 }), | ||
}) | ||
Comment on lines
+5
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider using snake_case for table and column names. While the current naming convention is consistent, it's generally recommended to use snake_case for table and column names in PostgreSQL. This aligns better with PostgreSQL conventions and avoids potential issues with case-sensitivity in queries. Here's how you could modify the schema to use snake_case: export const socialMedia = pgTable('social_media', {
id: serial('id').primaryKey(),
user_id: integer('user_id').notNull()
.references(() => user.id),
platform_name: varchar('platform_name', { length: 16 }).notNull(),
profile_url: varchar('profile_url', { length: 128 }).notNull(),
}, (table) => ({
userPlatformUnique: unique().on(table.user_id, table.platform_name),
})); Remember to update any references to these fields in other parts of your codebase if you make this change. π οΈ Refactor suggestion Consider adding additional useful fields to the schema. The current schema covers the basic needs for a social media link table. However, consider adding the following fields to enhance functionality and data tracking:
Here's an example of how you might implement these additions: import { integer, pgTable, serial, varchar, timestamp, pgEnum } from 'drizzle-orm/pg-core'
export const visibilityEnum = pgEnum('visibility', ['public', 'private', 'friends_only']);
export const socialMedia = pgTable('social_media', {
id: serial('id').primaryKey(),
user_id: integer('user_id').notNull()
.references(() => user.id),
platform_name: varchar('platform_name', { length: 16 }).notNull(),
profile_url: varchar('profile_url', { length: 128 }).notNull(),
visibility: visibilityEnum('visibility').default('public').notNull(),
created_at: timestamp('created_at').defaultNow().notNull(),
updated_at: timestamp('updated_at').defaultNow().notNull(),
}, (table) => ({
userPlatformUnique: unique().on(table.user_id, table.platform_name),
})); These additions would provide more comprehensive data management and user control over their social media links. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { boolean, integer, pgTable, serial, varchar } from 'drizzle-orm/pg-core' | ||
|
||
export const team = pgTable('team', { | ||
id: serial('id').primaryKey(), | ||
name: varchar('name', { length: 64 }), | ||
profileImageUrl: varchar('profileImageUrl', { length: 128 }), | ||
projectLinkUrl: varchar('projectLinkUrl', { length: 256 }), | ||
teamOwnerId: integer('teamOwnerId'), | ||
hasSubmitted: boolean('hasSubmitted').default(false), | ||
teamProfileImageUrl: varchar('teamProfileImageUrl', { | ||
length: 128, | ||
}), | ||
}) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,8 +1,36 @@ | ||||||
import { pgTable, text } from 'drizzle-orm/pg-core' | ||||||
import { boolean, date, integer, pgEnum, pgTable, serial, smallint, text, varchar } from 'drizzle-orm/pg-core' | ||||||
import { resume } from './resume' | ||||||
import { school } from './school' | ||||||
import { emergencyContact } from './emergencyContact' | ||||||
import { team } from './team' | ||||||
|
||||||
export const genderEnum = pgEnum('gender', ['male', 'female', 'other']) | ||||||
export const phoneNumberCountryCodeEnum = pgEnum('phoneNumberCountryCode', ['+1']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider expanding Currently, Possible code change: -export const genderEnum = pgEnum('gender', ['male', 'female', 'other'])
+export const genderEnum = pgEnum('gender', ['male', 'female', 'non-binary', 'prefer not to say', 'other']) Alternatively, you might use a π Committable suggestion
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well do this now, agree with this π There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @HasithDeAlwis, great! Happy to hear that you're making this update. π
If you found this review helpful, would you consider giving us a shout-out on X? |
||||||
export const ethnicityEnum = pgEnum('ethnicity', ['black', 'white', 'asian', 'hispanic', 'middle-eastern']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Re-evaluate The Possible code change: -export const phoneNumberCountryCodeEnum = pgEnum('phoneNumberCountryCode', ['+1'])
+export const phoneNumberCountryCodeEnum = varchar('phoneNumberCountryCode', { length: 5 }).notNull() This change allows for a wider range of country codes while ensuring the field is not null. π Committable suggestion
Suggested change
|
||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider further improvements to While the previous comment about
Example improvement: -export const ethnicityEnum = pgEnum('ethnicity', ['black', 'white', 'asian', 'hispanic', 'middle-eastern'])
+export const ethnicityEnum = pgEnum('ethnicity', ['black', 'white', 'asian', 'hispanic', 'middle_eastern', 'indigenous', 'pacific_islander', 'multiracial', 'other', 'prefer_not_to_say']) π Committable suggestion
Suggested change
|
||||||
export const user = pgTable('user', { | ||||||
id: text('id').primaryKey(), | ||||||
name: text('name'), | ||||||
email: text('email').notNull(), | ||||||
avatarUrl: text('avatar_url'), | ||||||
id: serial('id').primaryKey(), | ||||||
firstName: varchar('firstName', { length: 32 }).notNull(), | ||||||
middleName: varchar('middleName', { length: 32 }), | ||||||
lastName: varchar('lastName', { length: 32 }).notNull(), | ||||||
preferredName: varchar('preferredName', { length: 32 }), | ||||||
email: varchar('email', { length: 64 }).unique().notNull(), | ||||||
Comment on lines
+13
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider adding length validation for name fields While the Example: firstName: varchar('firstName', { length: 32 }).notNull().check(sql`length(firstName) >= 2`), |
||||||
isEmailVerified: boolean('isEmailVerified').default(false), | ||||||
avatarUrl: varchar('avatarUrl', { length: 128 }), | ||||||
profileDescription: text('profileDescription'), | ||||||
dateOfBirth: date('dateOfBirth'), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Add length constraint to Consider adding a maximum length constraint to the -profileDescription: text('profileDescription'),
+profileDescription: varchar('profileDescription', { length: 500 }), This change limits the description to 500 characters, which should be sufficient for most use cases while preventing potential abuse. π Committable suggestion
Suggested change
|
||||||
gender: genderEnum('gender'), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Add age validation for Consider adding a check constraint to ensure the user is of appropriate age: dateOfBirth: date('dateOfBirth').check(sql`dateOfBirth <= current_date - interval '13 years'`), This example ensures users are at least 13 years old, but adjust the age limit according to your application's requirements. |
||||||
phoneNumberCountryCode: phoneNumberCountryCodeEnum('phoneNumberCountryCode'), | ||||||
phoneNumber: varchar('phoneNumber', { length: 16 }).unique(), | ||||||
isPhoneNumberVerified: boolean('isPhoneNumberVerified').default(false), | ||||||
numHackathonsAttended: smallint('numHackathonsAttended').default(0), | ||||||
anyOtherComments: text('anyOtherComments'), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Add upper limit to Consider adding an upper limit to -numHackathonsAttended: smallint('numHackathonsAttended').default(0),
+numHackathonsAttended: smallint('numHackathonsAttended').default(0).check(sql`numHackathonsAttended >= 0 AND numHackathonsAttended <= 100`), This change ensures the value is non-negative and sets a reasonable upper limit of 100 hackathons. π Committable suggestion
Suggested change
|
||||||
isDomestic: boolean('isDomestic'), | ||||||
ethnicity: ethnicityEnum('ethnicity'), | ||||||
estimatedGradYear: integer('estimatedGradYear'), | ||||||
agreeToMlhReqs: boolean('agreeToMlhReqs').default(false), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Validate Add a check constraint to ensure estimatedGradYear: integer('estimatedGradYear').check(sql`estimatedGradYear BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) AND EXTRACT(YEAR FROM CURRENT_DATE) + 10`), This ensures the graduation year is between the current year and 10 years in the future. |
||||||
resumeId: integer('resumeId').references(() => resume.id), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reconsider default value for The Possible code change: -agreeToMlhReqs: boolean('agreeToMlhReqs').default(false),
+agreeToMlhReqs: boolean('agreeToMlhReqs').notNull(), By removing the default and adding π Committable suggestion
Suggested change
|
||||||
schoolId: integer('schoolId').references(() => school.id), | ||||||
emergencyContactId: integer('emergencyContactId').references(() => emergencyContact.id), | ||||||
teamId: integer('teamId').references(() => team.id), | ||||||
}) | ||||||
Comment on lines
+12
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider adding created_at and updated_at fields To improve record tracking and auditing capabilities, consider adding created_at: timestamp('created_at').defaultNow().notNull(),
updated_at: timestamp('updated_at').defaultNow().notNull(), These fields can be very useful for debugging, auditing, and analyzing user data over time. |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,28 @@ | ||||||
import { boolean, integer, pgEnum, pgTable, serial } from 'drizzle-orm/pg-core' | ||||||
import { user } from './user' | ||||||
|
||||||
export const preferredLanguageEnum = pgEnum('preferredLanguage', ['EN']) | ||||||
export const eventPreferencesEnum = pgEnum('eventPreferences', ['hardware', 'software']) | ||||||
export const shirtSizeEnum = pgEnum('shirtSize', ['XS', 'S', 'M', 'L', 'XL', 'XXL']) | ||||||
export const pronounsEnum = pgEnum('pronouns', ['he/him', 'she/her', 'they/them', 'other']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Add a 'Prefer not to say' option to Including a 'Prefer not to say' option allows users who do not wish to disclose their pronouns to have an appropriate selection. |
||||||
export const dietRestrictionsEnum = pgEnum('dietRestrictions', ['allergies', 'vegan', 'none']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Expand Currently, |
||||||
export const trackPreferencesEnum = pgEnum('trackPreferences', ['hardware', 'software']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Broaden the options in The |
||||||
export const interestsEnum = pgEnum('interests', ['languages']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Enhance The current -export const interestsEnum = pgEnum('interests', ['languages'])
+export const interestsEnum = pgEnum('interests', ['languages', 'AI/ML', 'web_development', 'data_science', 'cybersecurity', 'mobile_development', 'game_development', 'iot', 'blockchain', 'other']) π Committable suggestion
Suggested change
|
||||||
export const disabilitiesEnum = pgEnum('disabilities', ['mobility', 'visual', 'hearing', 'cognitive', 'mental']) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider adding 'Other' to Including an 'Other' option allows users with disabilities not listed to accurately represent their needs. |
||||||
export const applicableSkillsEnum = pgEnum('applicableSkills', ['JavaScript', 'TypeScript', 'Python', 'Java']) | ||||||
|
||||||
export const userPreferences = pgTable('userPreferences', { | ||||||
id: serial('id').primaryKey(), | ||||||
userId: integer('userId').references(() => user.id), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Specify To maintain referential integrity, it's important to define what happens to Apply the following change: - userId: integer('userId').references(() => user.id),
+ userId: integer('userId').references(() => user.id, { onDelete: 'cascade', onUpdate: 'cascade' }), π Committable suggestion
Suggested change
|
||||||
preferredLanguage: preferredLanguageEnum('preferredLanguage').default('EN'), | ||||||
eventPreferences: eventPreferencesEnum('eventPreferences'), | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Determine if If users can select multiple event preferences, you should define Update the field as follows: - eventPreferences: eventPreferencesEnum('eventPreferences'),
+ eventPreferences: eventPreferencesEnum('eventPreferences').array(),
|
||||||
privacyMode: boolean('privacyMode').default(false), | ||||||
isSubscribedToNewsletter: boolean('isSubscribedToNewsletter').default(false), | ||||||
shirtSize: shirtSizeEnum('shirtSize'), | ||||||
pronouns: pronounsEnum('pronouns'), | ||||||
dietRestrictions: dietRestrictionsEnum('dietRestrictions').array(), | ||||||
trackPreferences: trackPreferencesEnum('trackPreferences').array(), | ||||||
interests: interestsEnum('interests').array(), | ||||||
disabilities: disabilitiesEnum('disabilities').array(), | ||||||
applicableSkills: applicableSkillsEnum('applicableSkills').array(), | ||||||
}) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Add timestamps for record tracking. Including Add the following fields to your table definition: + createdAt: timestamp('createdAt').defaultNow(),
+ updatedAt: timestamp('updatedAt').defaultNow().onUpdateNow(), Ensure you import import { boolean, integer, pgEnum, pgTable, serial, timestamp } from 'drizzle-orm/pg-core'
Comment on lines
+14
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π οΈ Refactor suggestion Consider adding a unique constraint on To ensure that each user has only one set of preferences, you might want to add a unique constraint on the Add the following after the table definition: export const userPreferencesConstraints = pgTable('userPreferences', {
userIdUnique: unique('userIdUnique').on(userPreferences.userId),
}) Don't forget to import -import { boolean, integer, pgEnum, pgTable, serial, timestamp } from 'drizzle-orm/pg-core'
+import { boolean, integer, pgEnum, pgTable, serial, timestamp, unique } from 'drizzle-orm/pg-core' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be worth adding a comment here explaining why we need this!