· 3 min read
#027
Setting Up DrizzleORM with NestJS
Purpose
This blog post is to document down the Step by Step Process on how to setup DrizzleORM in NestJS and walk through the code structure of the setup
High Level
File Structure
π¦ book-rental-backend-v2
β π drizzle/ # Generated migrations (drizzle-kit output)
β β π 0000_round_mystique.sql
β β π meta/
β β π _journal.json
β β π 0000_snapshot.json
β π src/
β β π database/
β β β π drizzle.module.ts # Global NestJS module exporting the DB provider
β β β π drizzle.provider.ts # Drizzle instance factory (NodePgDatabase)
β β β π schema/
β β β π index.ts # Re-exports all schema tables/enums
β β β π book.ts # Book table + statusEnum definition
β β π app.module.ts
β β π app.controller.ts
β β π app.service.ts
β β π main.ts
β π .env # DATABASE_URL used by Drizzle
β π drizzle.config.ts # Drizzle Kit config (schema path, dialect, out dir)
β π package.json
β π tsconfig.json
The above file structure is similar with the one suggested in DrizzleORM, I just rename src/db to src/database for my own preference.
I keep all database related code within the database folder except the drizzle.config.ts. The drizzle.config.ts will sit in the project root.
Step by Step Guide
Pre-requisite:
- Add DATABASE_URL into your .env file
- Install required dependencies for the DrizzleORM, you could find it from the Getting Started page.
Now letβs dive into the steps.
- I always start with the drizzle.config.ts to configure the database connection config 1st.
import "dotenv/config";
import { defineConfig } from "drizzle-kit";
export default defineConfig({
out: "./drizzle",
schema: "./src/database/schema/*.ts",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
- Now we will setup the require components in NestJS which is the Provider and Module
// src/database/drizzle.provider.ts
import { Provider } from "@nestjs/common";
import { drizzle, NodePgDatabase } from "drizzle-orm/node-postgres";
import * as schema from "./schema";
export const DRIZZLE_PROVIDER = "DRIZZLE_DB";
export type DrizzleDB = NodePgDatabase<typeof schema>;
export const drizzleProvider: Provider = {
provide: DRIZZLE_PROVIDER,
// eslint-disable-next-line @typescript-eslint/require-await
useFactory: async () => {
const db = drizzle(process.env.DATABASE_URL!, { schema });
return db;
},
};
// src/database/drizzle.module.ts
import { Module, Global } from "@nestjs/common";
import { drizzleProvider } from "./drizzle.provider";
@Global() // Makes it available app-wide without re-importing
@Module({
providers: [drizzleProvider],
exports: [drizzleProvider],
})
export class DrizzleModule {}
- Now your you can use your DrizzleDB Connection in your NestJS Service through dependency injection. Here is an example.
@Injectable()
export class BookService {
constructor(@Inject(DRIZZLE_PROVIDER) private readonly db: DrizzleDB) {}
async create(createBookDto: CreateBookDto) {
const [created] = await this.db
.insert(book)
.values({
name: createBookDto.name,
author: createBookDto.author,
status: createBookDto.status ?? BookStatus.AVAILABLE,
})
.returning();
return created;
}
}
References
- Drizzle ORM Get Started Guide