Skip to content

Модуль Drizzle интегрирует drizzle-orm с системой внедрения зависимостей nestelia. Модуль не зависит от диалекта — работает с любой базой данных, поддерживаемой drizzle (PostgreSQL, MySQL, SQLite).

Установка

bash
bun add drizzle-orm

Добавьте драйвер для вашей базы данных:

bash
# PostgreSQL
bun add postgres        # postgres.js (рекомендуется)
bun add pg              # node-postgres

# MySQL
bun add mysql2

# SQLite (не требует доп. установки в Bun)
# bun:sqlite встроен в Bun

# LibSQL / Turso
bun add @libsql/client

Настройка

Создайте экземпляр drizzle и передайте его в DrizzleModule.forRoot():

typescript
import { Database } from "bun:sqlite";
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Module } from "nestelia";
import { DrizzleModule } from "nestelia/drizzle";
import * as schema from "./schema";

const sqlite = new Database("app.db");
const db = drizzle(sqlite, { schema });

@Module({
  imports: [
    DrizzleModule.forRoot({ db, isGlobal: true }),
  ],
})
export class AppModule {}

Пример с PostgreSQL

typescript
import postgres from "postgres";
import { drizzle } from "drizzle-orm/postgres-js";
import * as schema from "./schema";

const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });

DrizzleModule.forRoot({ db, isGlobal: true })

Асинхронная конфигурация

Используйте forRootAsync, если строка подключения берётся из сервиса конфигурации или окружения:

typescript
import { DrizzleModule } from "nestelia/drizzle";
import { ConfigService } from "./config.service";
import * as schema from "./schema";

DrizzleModule.forRootAsync({
  isGlobal: true,
  inject: [ConfigService],
  useFactory: (config: ConfigService) => {
    const client = postgres(config.get("DATABASE_URL"));
    return { db: drizzle(client, { schema }) };
  },
})

useClass / useExisting

typescript
import { DrizzleOptionsFactory, DrizzleModuleOptions } from "nestelia/drizzle";
import { Injectable } from "nestelia";

@Injectable()
class DatabaseConfig implements DrizzleOptionsFactory {
  constructor(private readonly config: ConfigService) {}

  createDrizzleOptions(): DrizzleModuleOptions {
    const client = postgres(this.config.get("DATABASE_URL"));
    return { db: drizzle(client, { schema }) };
  }
}

DrizzleModule.forRootAsync({ useClass: DatabaseConfig })

Определение схемы

typescript
// src/schema.ts
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const users = sqliteTable("users", {
  id: integer("id").primaryKey({ autoIncrement: true }),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
});

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;

Инжектирование базы данных

@InjectDrizzle()

Используйте декоратор @InjectDrizzle() как сокращение для @Inject(DRIZZLE_INSTANCE):

typescript
import { Injectable } from "nestelia";
import { InjectDrizzle } from "nestelia/drizzle";
import { eq } from "drizzle-orm";
import { drizzle } from "drizzle-orm/bun-sqlite";
import * as schema from "./schema";

type DB = ReturnType<typeof drizzle<typeof schema>>;

@Injectable()
export class UsersService {
  constructor(@InjectDrizzle() private readonly db: DB) {}

  findAll() {
    return this.db.select().from(schema.users).all();
  }

  findOne(id: number) {
    return this.db
      .select()
      .from(schema.users)
      .where(eq(schema.users.id, id))
      .get();
  }

  create(data: schema.NewUser) {
    return this.db
      .insert(schema.users)
      .values(data)
      .returning()
      .get();
  }
}

Использование токена напрямую

typescript
import { Injectable, Inject } from "nestelia";
import { DRIZZLE_INSTANCE } from "nestelia/drizzle";

@Injectable()
export class UsersService {
  constructor(@Inject(DRIZZLE_INSTANCE) private readonly db: DB) {}
}

Несколько баз данных

Зарегистрируйте каждую БД с уникальным tag и инжектируйте по тому же тегу:

typescript
// app.module.ts
@Module({
  imports: [
    DrizzleModule.forRoot({ db: primaryDb }),
    DrizzleModule.forRoot({ db: analyticsDb, tag: "analytics" }),
  ],
})
export class AppModule {}
typescript
// report.service.ts
@Injectable()
export class ReportService {
  constructor(
    @InjectDrizzle() private readonly primary: PrimaryDB,
    @InjectDrizzle("analytics") private readonly analytics: AnalyticsDB,
  ) {}
}

Справочник опций

DrizzleModuleOptions

СвойствоТипПо умолчаниюОписание
dbunknownНастроенный экземпляр drizzle-orm (обязательно)
tagstring | symbolDRIZZLE_INSTANCEПользовательский токен инжекции
isGlobalbooleanfalseЗарегистрировать как глобальный модуль

DrizzleModuleAsyncOptions

СвойствоТипОписание
tagstring | symbolПользовательский токен инжекции
isGlobalbooleanЗарегистрировать как глобальный модуль
importsany[]Модули для импорта в область видимости
useFactory(...args) => DrizzleModuleOptionsФабричная функция
injectany[]Зависимости для фабрики
useClassType<DrizzleOptionsFactory>Класс, реализующий DrizzleOptionsFactory
useExistingType<DrizzleOptionsFactory>Существующий провайдер
extraProvidersProvider[]Дополнительные провайдеры в области модуля

Экспорты

ЭкспортОписание
DrizzleModuleКласс модуля
InjectDrizzle(tag?)Сокращённый декоратор параметра
DRIZZLE_INSTANCEТокен инжекции по умолчанию
DRIZZLE_MODULE_OPTIONSТокен для сырых опций
DrizzleModuleOptionsИнтерфейс синхронных опций
DrizzleModuleAsyncOptionsИнтерфейс асинхронных опций
DrizzleOptionsFactoryФабричный интерфейс для useClass / useExisting

Распространяется по лицензии MIT.