

0 / 2 embers
0 / 3000 xp
click for more info
Complete a lesson to start your streak
click for more info
Difficulty: 5
click for more info
Not enough gems
Cost: 6 gems
1: Storage
incomplete
2: Drizzle ORM
incomplete
3: Drizzle Queries
incomplete
4: Automatic Migrations
incomplete
5: Database Review
incomplete
6: Create User
incomplete
7: Create Chirp
incomplete
8: Collections and Singletons
incomplete
9: Get All Chirps
incomplete
10: Get Chirp
incomplete
Back
ctrl+,
Next
ctrl+.
This lesson's interactive features are locked, please to keep using them
Drizzle is a ORM and migration tool written in TypeScript. Its API and syntax is very similar to SQL, making it a perfect fit for this project (we wanna stay close to the raw SQL).
A migration is just a set of changes to your database table. You can have as many migrations as needed as your requirements change over time. For example, one migration might create a new table, one might delete a column, and one might add 2 new columns.
An "up" migration moves the state of the database from its current schema to the schema that you want. So, to get a "blank" database to the state it needs to be ready to run your application, you run all the "up" migrations.
If something breaks, you can run one of the "down" migrations to revert the database to a previous state. "Down" migrations are also used if you need to reset a local testing database to a known state.
npm i drizzle-orm postgres
npm i -D drizzle-kitI keep database-related files in src/db. The paths below follow that layout; if yours differs, update the configuration paths and imports to match.
id: a UUID that will serve as the primary key
created_at: a TIMESTAMP that can not be null
updated_at: a TIMESTAMP that can not be null
email: VARCHAR(256) that can not be null and must be unique.
import { pgTable, timestamp, varchar, uuid } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: uuid("id").primaryKey().defaultRandom(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at")
.notNull()
.defaultNow()
.$onUpdate(() => new Date()),
email: varchar("email", { length: 256 }).unique().notNull(),
});
export type NewUser = typeof users.$inferInsert;The $onUpdate function sets the updatedAt field to a default value whenever the row is updated.
$inferInsert is a helper type that infers the type of the object you would pass to the insert function. This is useful for type safety.
protocol://username:password@host:port/databaseHere are examples:
macOS (no password, your username): postgres://wagslane:@localhost:5432/chirpy
Linux (password from last lesson, postgres user): postgres://postgres:postgres@localhost:5432/chirpy
Test your connection string by running psql, for example:
psql "postgres://wagslane:@localhost:5432/chirpy"It should connect you to the chirpy database directly. If it's working, great. exit out of psql and save the connection string.
We're hard-coding the connection string for now. Don't worry, we'll change that soon - just don't commit it to your Git history.
import { defineConfig } from "drizzle-kit";
export default defineConfig({
schema: "./src/db/schema.ts",
out: "./src/db/migrations",
dialect: "postgresql",
dbCredentials: {
url: "your_connection_string",
},
});protocol://username:password@host:port/database?sslmode=disableYour application code needs to know to not try to use SSL locally.
npx drizzle-kit generatenpx drizzle-kit migrateRun and submit the CLI tests.
You can add scripts to your package.json to make running drizzle-kit easier. For example:
{
"scripts": {
"generate": "drizzle-kit generate",
"migrate": "drizzle-kit migrate"
}
}