nnestjs-drizzle-crud
Configuration

forRootAsync

Configure the database connection asynchronously, e.g. from ConfigService.

DrizzleCrudModule.forRootAsync(options) is the asynchronous variant of forRoot. Use it when your configuration is built at runtime, typically read from ConfigService after env validation.

Signature

DrizzleCrudModule.forRootAsync({
  imports?: ModuleClass[];
  useFactory: (...deps: any[]) => Promise<DrizzleCrudConfig> | DrizzleCrudConfig;
  inject?: any[];
}): DynamicModule

Example: with @nestjs/config

app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    DrizzleCrudModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (cfg: ConfigService) => ({
        dialect: 'postgresql',
        connectionString: cfg.getOrThrow<string>('DATABASE_URL'),
        schema,
        defaults: {
          pagination: { defaultLimit: 20, maxLimit: 100 },
        },
      }),
    }),
  ],
})
export class AppModule {}

The useFactory may return a Promise<DrizzleCrudConfig> if you need to read from a remote source (Vault, AWS SSM, etc.) before constructing the config object.

Example: pre-built Drizzle instance with config

app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    DrizzleCrudModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (cfg: ConfigService) => {
        const client = postgres(cfg.getOrThrow<string>('DATABASE_URL'));
        return {
          dialect: 'postgresql',
          db: drizzle(client, { schema }),
        };
      },
    }),
  ],
})
export class AppModule {}

Example: multiple injected services

DrizzleCrudModule.forRootAsync({
  imports: [ConfigModule, FeatureFlagsModule],
  inject: [ConfigService, FeatureFlagsService],
  useFactory: (cfg: ConfigService, flags: FeatureFlagsService) => ({
    dialect: 'postgresql',
    connectionString: cfg.getOrThrow('DATABASE_URL'),
    schema,
    sql: {
      enableFullTextSearch: flags.isEnabled('fts'),
    },
  }),
})

useClass / useExisting

forRootAsync exposes useFactory directly. It does not accept useClass or useExisting. If you need a class-based config, wrap it:

class CrudConfigService {
  constructor(private readonly cfg: ConfigService) {}
  create() {
    return { dialect: 'postgresql' as const, /* ... */ };
  }
}

DrizzleCrudModule.forRootAsync({
  imports: [ConfigModule],
  inject: [CrudConfigService, ConfigService],
  useFactory: (svc: CrudConfigService) => svc.create(),
})

When to use forRoot vs forRootAsync

Use forRoot when the config object can be built statically at module-evaluation time. Use forRootAsync when any of:

  • The connection string is read from process.env and you want validation via ConfigService.
  • The Drizzle instance is built from config (e.g. dynamic pool size).
  • You depend on another provider in useFactory (feature flags, secrets manager).

Next

On this page