Database
The database for Cooper is managed by Drizzle.
Drizzle is a performant database toolkit that makes it easy to access databases with type safety and auto-completion. It is used to define the data model and generate the database schema. All of the database-related code is within the db
package. All of the database schemas are defined in the /schema
folder.
Example Schema
export const Role = pgTable("role", {
id: uuid("id").notNull().primaryKey().defaultRandom(),
title: varchar("title").notNull(),
description: text("description"),
companyId: varchar("companyId").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updatedAt", {
mode: "date",
withTimezone: true,
}).$onUpdateFn(() => sql`now()`),
});
In the above example, the Role
table is defined with the following columns:
id
- a UUID primary keytitle
- a string that is not nullabledescription
- a nullable text fieldcompanyId
- a string that is not nullable (foreign key to theCompany
table)createdAt
- a timestamp that defaults to the current timeupdatedAt
- a timestamp that defaults to the current time and is updated on every update
export const RoleRelations = relations(Role, ({ one, many }) => ({
company: one(Company, {
fields: [Role.companyId],
references: [Company.id],
}),
reviews: many(Review),
}));
We also define a one-to-many relationship with the Review
table and a one-to-one relationship with the Company
table.
export const CreateRoleSchema = createInsertSchema(Role, {
title: z.string(),
description: z.string(),
companyId: z.string(),
}).omit({
id: true,
createdAt: true,
updatedAt: true,
});
Finally, we also define an insert schema using drizzle-zod for creating a new role. This schema is used to validate the input data before inserting it into the database and is used by the tRPC API for creating a new role.
Authentication-Related Tables
The following tables are used for authentication and are entirely managed by NextAuth:
Account
Session
User
See NextAuth Drizzle documentation for more information.
Database Management
Generate
From the root of the project, you can run the following command to generate the database schema:
pnpm db:generate
The usual workflow is to modify the database is the following:
-
Modify the schema in the
/schema
folder. -
Update
schema.ts
to include any new schema files (if necessary). -
Run
pnpm db:generate
to generate the database schema.
Once you run the generate command, the migration will be added drizzle
folder. A new SQL file will be generated with the changes to the database schema. In certain cases, running the command will prompt the user to select one of the alternatives for the migration before generating the SQL file.
Migrate
To apply the generated migration to the database, you can run the following command:
pnpm db:migrate
This command will apply the migration to the database and update the schema in the database in order of the SQL files in the drizzle
folder.
Push
To directly push the schema to the database, you can run the following command:
pnpm db:push
It is not recommended to use this command in production as it will directly push the schema to the database without sequentially applying the migrations. This command is useful for development purposes when you want to quickly update the database.
Studio
To open the Drizzle Studio, you can run the following command:
pnpm db:studio
This will open the Drizzle Studio in your browser where you can view the database schema and run queries. This is very useful when it comes to creating new companies or roles since we currently don't have a way of doing that through the UI.