forRoot
Configure the database connection once in AppModule via DrizzleCrudModule.forRoot.
DrizzleCrudModule.forRoot(config) is called once in your AppModule. It owns the database connection, exposes it globally, and closes it on application shutdown (when the module built it from a connectionString).
Signature
DrizzleCrudModule.forRoot(config: DrizzleCrudConfig): DynamicModuleOptions
| Field | Type | Description |
|---|---|---|
dialect | 'postgresql' | 'mysql' | Required. Database dialect. |
connectionString | string | Connection string. The module builds the connection (PostgreSQL only). |
db | Drizzle instance | Alternatively, pass a Drizzle instance you built yourself (any dialect). |
schema | Record<string, unknown> | Drizzle schema, used when building from connectionString. |
defaults.softDelete | boolean | Enable soft delete for all entities (default true). |
defaults.timestamps | boolean | Auto-manage created_at / updated_at for all entities (default true). |
defaults.pagination | { defaultLimit?: number; maxLimit?: number } | Pagination defaults (default { 20, 100 }). Set one key and the other keeps its default. |
defaults.sortOrder | 'asc' | 'desc' | Opt-in default sort. Entities without an explicit defaultSort fall back to ordering by their created_at column in this direction. Omit it and findAll orders by the primary key only. |
sql | { caseSensitive?, useReturning? } | Dialect tuning. useReturning defaults to true for PostgreSQL, false for MySQL. Every key is optional. |
Provide exactly one of connectionString or db. The module will throw
if you pass neither, or both.
If your tables have no created_at / updated_at / deleted_at columns,
set defaults: { softDelete: false, timestamps: false }. If your schema
uses camelCase keys (deletedAt: timestamp('deleted_at')), set the key
names per entity in forFeature. Since 3.3.1 a service whose configured
soft-delete or timestamp key is not on its table fails at startup, and the
message names the key to use.
PostgreSQL: let the module build the connection
import { Module } from '@nestjs/common';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';
@Module({
imports: [
DrizzleCrudModule.forRoot({
dialect: 'postgresql',
connectionString: process.env.DATABASE_URL,
schema,
defaults: {
softDelete: true,
timestamps: true,
pagination: { defaultLimit: 20, maxLimit: 100 },
},
sql: {
caseSensitive: false,
},
}),
],
})
export class AppModule {}The module imports the postgres driver on your behalf and builds a Drizzle instance from your schema. The connection is closed automatically on app shutdown.
Build the connection yourself (any dialect, recommended for MySQL)
If you want full control over the connection (pool size, SSL, advanced mysql2 options), or you are on MySQL, pre-build the Drizzle instance and pass it as db:
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';
const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });
@Module({
imports: [
DrizzleCrudModule.forRoot({
dialect: 'postgresql',
db,
}),
],
})
export class AppModule {}import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import { DrizzleCrudModule } from 'nestjs-drizzle-crud';
import { schema } from './db/schema';
const pool = mysql.createPool({
uri: process.env.DATABASE_URL,
connectionLimit: 10,
});
const db = drizzle(pool, { schema });
@Module({
imports: [
DrizzleCrudModule.forRoot({
dialect: 'mysql',
db,
}),
],
})
export class AppModule {}When you pass db, the module does not close the connection on
shutdown. Closing it is your responsibility, and that makes it easy to share the same
pool across other Drizzle consumers (custom services, raw queries,
migrations).
sql tuning
| Option | Default | What it does |
|---|---|---|
caseSensitive | false | When false, bare string filter values are compiled to lower(column) = lower(value) (case-insensitive exact match). When true, bare strings use plain equality (collation-dependent). Use the explicit { like } / { ilike } operators for pattern matching. |
useReturning | true (Postgres) / false (MySQL) | Use RETURNING after INSERT to fetch the created row. MySQL does not support RETURNING, so leave it off. |
jsonSupport | true | Deprecated, no effect. Nothing reads it. It is still accepted so existing configs compile, and will be removed in the next major version. |
enableFullTextSearch | false | Deprecated, no effect. fullTextSearch() and search.mode: 'fullText' work on PostgreSQL whatever this is set to. Removed in the next major version. |
hooks.enableGlobalHooks is deprecated too: there are no global hooks, so it does nothing. Override the hooks on each service instead.
caseSensitive: false only applies lower() to text columns (text, varchar, char). A string filter on an integer, uuid or enum column is a plain =, so a query string value such as ?author_id=1 works.
Defaults cheat sheet
defaults: {
softDelete: true, // deletes set deleted_at = now()
timestamps: true, // create/update stamp created_at/updated_at
pagination: { defaultLimit: 20, maxLimit: 100 },
sortOrder: 'desc', // opt-in: created_at fallback for findAll
},
sql: {
caseSensitive: false,
useReturning: dialect === 'postgresql',
}When to use forRootAsync
If your config comes from ConfigService (env validation, secrets, dynamic config), use forRootAsync instead of forRoot.