在 Nestjs 中使用 Drizzle ORM

在 Nestjs 中使用 Drizzle ORM

依赖安装

shell
pnpm add drizzle-orm pg dotenv
pnpm add -D drizzle-kit tsx @types/pg

准备 DrizzleModule

这里我们都在 /src/drizzle 目录中操作

创建 drizzle.provider.ts 文件

创建 drizzle.service.ts 文件

有了这个以后,我们可以在后续的模块中直接注入该模块 constructor(private readonly drizzle: DrizzleService) {},而不是每次都要写 constructor(@Inject(PG_CONNECTION) readonly db: NodePgDatabase<Schema>) {} 这么一长串内容

drizzle.service.tsts
import { Inject, Injectable } from '@nestjs/common';
import { NodePgDatabase } from 'drizzle-orm/node-postgres';

import type { Schema } from './schema';

import { PG_CONNECTION } from './drizzle.provider';

@Injectable()
export class DrizzleService {
    constructor(@Inject(PG_CONNECTION) readonly db: NodePgDatabase<Schema>) {}
}

创建 drizzle.module.ts 文件

drizzle.module.tsts
import { Global, Module } from '@nestjs/common';

import { DrizzleProvider } from './drizzle.provider';
import { DrizzleService } from './drizzle.service';

@Global()
@Module({
    imports: [],
    providers: [DrizzleService, DrizzleProvider],
    exports: [DrizzleService],
})
export class DrizzleModule {}

创建数据库 Schema

创建一个 user.entity.ts

创建 schema.ts 文件

schema.tsts
import { user } from './user.entity';

export type { SelectUser } from './user.entity';

export const schema = {
    user
}

export type Schema = typeof schema;
export type SchemaName = keyof Schema;

这样我们的 DrizzleModule 就准备好了

drizzle 相关的配置

我们要在项目根目录下创建 drizzle.config.ts 文件,这个文件是 DrizzleOrm 的配置文件

drizzle.config.tsts
import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';

export default defineConfig({
    schema: './src/drizzle/schema/**.entity.ts', // 这里是数据库 schema 文件的位置
    out: './drizzle/migrations', // 数据库迁移文件生成的地址
    dialect: 'postgresql', // 数据库驱动
    dbCredentials: {
        url: process.env.DATABASE_URL!,
    },
});

package.json 中的脚本

json
{
  "scripts": {
    "db:generate": "drizzle-kit generate",
    "db:migrate": "drizzle-kit migrate",
    "db:push": "drizzle-kit push",
    "db:studio": "drizzle-kit studio",
  },
}
  • db:generate 声明时或后续 Schema 更改时基于 Drizzle Schema 生成 SQL 迁移
  • db:migrate 运行迁移后,Drizzle Kit 会将成功应用的迁移记录保存到数据库中。
  • db:push 允许您直接将您的架构和后续架构更改推送到数据库
  • db:studio 本地数据库可视化面板

生成 schema 并将改动同步到数据库

shell
pnpm run db:generate
shell
pnpm run db:migrate

成功后我们可以使用 pnpm run db:studio 查看数据库中的内容。

在 app.module.ts 中引入 DrizzleModule

app.module.tsts
@Module({
    imports: [
    // ...
        DrizzleModule,
    ],
})
export class AppModule {}

在模块中使用,这里用 UserModule 作为例子

附加内容

vscode 插件推荐

vscode-drizzle-orm

数据库填充

在开发中我们通常都要填充一些模拟数据用来测试,那么在 nestjs + drizzle 这个组合下我们如何操作呢?

我们还是在 src/drizzle 文件夹中操作

创建 db.ts

db.tsts
import 'dotenv/config';
import { drizzle, NodePgDatabase } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';

import { Schema, schema } from './schema';

const connectionString = process.env.DATABASE_URL;

if (!connectionString) {
    throw new Error('DATABASE_URL is not defined');
}

const pool = new Pool({ connectionString });
export const db: NodePgDatabase<Schema> = drizzle(pool, { schema, logger: true });

export type db = NodePgDatabase<Schema>;

创建 seed 相关文件

seeds/user.seed.tsts
import { hashSync } from 'bcrypt';

import { db } from '@/drizzle/db';

import { schema } from '../schema';

export async function seedUser(db: db) {
    await db.insert(schema.user).values([
        { username: 'admin', password: hashSync('123456', 10) },
        { username: 'user', password: hashSync('123456', 10) },
    ]);
}

在 package.json 中添加命令

json
{
  "db:seed": "ts-node ./src/drizzle/seed.ts"
}

我们就可以运行 pnpm run db:seed 来进行数据库填充了

在 nestjs 中使用 scalar
nest-config 模块的人体工学适配