Lab 14: Drizzle ORM Type-Safe
Step 1: Environment Setup
docker run -it --rm node:20-alpine sh
apk add --no-cache python3 make g++
npm install -g typescript ts-node
mkdir lab14 && cd lab14
npm init -y
npm install drizzle-orm better-sqlite3 @types/better-sqlite3
echo '{"compilerOptions":{"module":"commonjs","target":"es2020","strict":false,"esModuleInterop":true,"moduleResolution":"node"}}' > tsconfig.jsonStep 2: Schema Definition
// schema.ts
import { sqliteTable, text, integer, real, blob } from 'drizzle-orm/sqlite-core';
import { relations } from 'drizzle-orm';
import { sql } from 'drizzle-orm';
// Users table
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
email: text('email').notNull().unique(),
role: text('role', { enum: ['admin', 'editor', 'viewer'] }).default('viewer').notNull(),
createdAt: text('created_at').default(sql`CURRENT_TIMESTAMP`).notNull(),
active: integer('active', { mode: 'boolean' }).default(true).notNull(),
});
// Posts table
export const posts = sqliteTable('posts', {
id: integer('id').primaryKey({ autoIncrement: true }),
title: text('title').notNull(),
content: text('content').notNull(),
published: integer('published', { mode: 'boolean' }).default(false).notNull(),
authorId: integer('author_id').notNull().references(() => users.id),
views: integer('views').default(0).notNull(),
score: real('score').default(0.0),
createdAt: text('created_at').default(sql`CURRENT_TIMESTAMP`).notNull(),
});
// Tags table
export const tags = sqliteTable('tags', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull().unique(),
color: text('color').default('#gray'),
});
// Post-Tags junction
export const postTags = sqliteTable('post_tags', {
postId: integer('post_id').notNull().references(() => posts.id),
tagId: integer('tag_id').notNull().references(() => tags.id),
});
// Relations (for query builder joins)
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one, many }) => ({
author: one(users, { fields: [posts.authorId], references: [users.id] }),
postTags: many(postTags),
}));
// TypeScript types inferred from schema
export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;
export type Post = typeof posts.$inferSelect;
export type NewPost = typeof posts.$inferInsert;
export type Tag = typeof tags.$inferSelect;Step 3: Database Setup and Connection
Step 4: INSERT Operations
Step 5: SELECT with WHERE and Operators
Step 6: UPDATE and DELETE
Step 7: drizzle-kit Migrations Concept
Step 8: Capstone — Complete Data Layer
Summary
Operation
Drizzle API
Type Safety
Last updated
